下载:
- #include <myhead.h>
-
- #define ERR(s) do\
- {\
- fprintf(stderr,"__%d__",__LINE__);\
- perror(s);\
- }while(0)
- #define PORT 69
- #define IP "192.168.115.184"
-
- int do_download(int cfd,struct sockaddr_in sin);
- //int do_upload();
- int main(int argc, const char *argv[])
- {
-
- //创建报式套接字socket
- int cfd;
- if((cfd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
- {
- ERR("socket");
- return -1;
- }
- printf("socket success\n");
-
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(PORT);
- sin.sin_addr.s_addr = inet_addr(IP);
- char choose = 0;
- while(1)
- {
- system("clear");
- printf("--------------------------------\n");
- printf("-------------1下载--------------\n");
- printf("-------------2上传--------------\n");
- printf("-------------3退出--------------\n");
- printf("--------------------------------\n");
- printf("请输入>>>");
- scanf("%c",&choose);
- while(getchar()!=10); //吸收垃圾字符
- switch(choose)
- {
- case '1':
- do_download(cfd,sin);
- break;
- case '2':
- //do_upload();
- break;
- case '3':
- goto END;
- break;
- default :
- printf("输入错误,请重新输入\n");
- }
- printf("请输入任意字符清屏\n");
- while(getchar()!=10);
- }
- END:
- //关闭套接字
- close(cfd);
- return 0;
- }
-
- int do_download(int cfd,struct sockaddr_in sin)
- {
- /*
- //组下载请求包
- char buf[516] = "";
- char f_n[20] = "";
- //操作码
- unsigned short *ptr1 = (unsigned short*)buf;
- *ptr1 = htons(1); //组操作码
- //文件名
- char *ptr2 = (char *)(ptr1+1);
- strcpy(ptr2,f_n);
- //模式
- char *ptr3 = ptr2 + strlen(f_n) + 1;
- strcpy(ptr3,"octet");
-
- int size = 2+strlen(ptr2)+1+strlen(ptr3)+1;
- */
- char buf[516] = "";
- char f_n[20] = "";
- int num=1;
- printf("请输入文件名>>> ");
- //终端输入要下载的文件名
- fgets(f_n,sizeof(f_n),stdin);
- f_n[strlen(f_n)-1] = '\0';
- int fd;
- if((fd = open(f_n,O_WRONLY|O_CREAT|O_TRUNC,0664)) == -1)
- {
- ERR("open");
- return -1;
- }
- //用sprintf拼接
- int size = sprintf(buf,"%c%c%s%c%s%c",0,1,f_n,0,"octet",0);
- //发送下载请求sendto
- if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) < 0 )
- {
- ERR("sendto askpackage");
- return -1;
- }
- printf("sendto askpackage success\n");
- ssize_t len = 0;
- struct sockaddr_in addrin;
- socklen_t addrlen=sizeof(addrin);
- while(1)
- {
- //清空buf
- bzero(buf,sizeof(buf));
- //接收数据recvfrom,接收地址信息
- if((len = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&addrin,&addrlen)) < 0)
- {
- ERR("recvfrom datapackage");
- return -1;
- }
- unsigned short ptr2=ntohs(*(unsigned short*)(buf+2));
- printf("%hu\n",ptr2);
- //当操作码为5时
- if(5 == buf[1])
- {
- fprintf(stderr, "错误码:%d,错误信息:%s\n", ntohs(*(unsigned short*)(buf+2)), buf+4);
- break;
- }
- //当操作码为3,并且块编号正确时
- else if(3 == buf[1] && num == ptr2)
- {
- printf("%d\n",fd);
- //跳过前四个字节,写入文件
-
- if(write(fd,buf+4,len-4)<0)
- {
- ERR("write");
- return -1;
- }
-
- //组ACK包
- buf[1] = 4;
- //发送ACK包,sendto
- if(sendto(cfd,buf,4,0,(struct sockaddr*)&addrin,addrlen) < 0)
- {
- ERR("sendto ACKpackage");
- return -1;
- }
- num++;
- //判断数据是否小于512个字节,若小于则下载完成
- if(len < 516)
- {
- printf("download success\n");
- break;
- }
- }
- }
- close(fd);
- return 0;
- }