代码:
#include <myhead.h>//实现下载功能
int download(int cfd,struct sockaddr_in sin)
{char buf[516] = ""; //定义资源包char fileName[128] = ""; //定义文件名printf("请输入文件名:");scanf("%s",fileName); getchar();//打开文件int fd = -1;if((fd = open(fileName,O_RDWR|O_CREAT|O_TRUNC|0666)) == -1){perror("open error"); //读写形式创建文件,文件名为输入的文件名return -1;}//组装请求包short *p1 = (short *)buf;*p1 = htons(1);char *p2 = buf + 2;strcpy(p2,fileName);char *p3 = p2+strlen(p2)+1;strcpy(p3,"octet"); int size = 4+strlen(p2)+strlen(p3); //整体长度//先发送下载请求到服务器if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto error");return -1;}printf("请求成功!\n");socklen_t socklen = sizeof(sin);char *p5 = buf + 4; //确定数据的位置以及差错信息的位置while(1){bzero(buf,sizeof(buf));int res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);int A = buf[1]; //因为小端存储,操作码放在buf的第二位if(A == 3) //当操作码为3时,证明是数据包,正常接收{write(fd,p5,sizeof(buf));buf[1]=4; //将操作码改为4,即ACK//将buf前四位发送回去,因为操作码已经修改,发回去四位当做ACK回复sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));}else if(A == 5) //当操作码为5时,证明为ERROR{printf("%s\n",p5);return -1;}if(res < 516) //当接收到的字节数小于516时,证明已经接收完成,关闭循环break;}printf("下载完成\n");close(fd); //关闭文件
}//实现上传功能
int upload(int cfd,struct sockaddr_in sin)
{char buf[516] = ""; //定义资源包char fileName[128] = ""; //定义文件名printf("请输入文件名:");scanf("%s",fileName); getchar();//打开文件int fd = -1;if((fd = open(fileName,O_RDONLY)) == -1){perror("open error"); //只读形式打开文件,文件名为输入的文件名return -1;}//组装请求包short *p1 = (short *)buf;*p1 = htons(2); //操作码为2代表要上传char *p2 = buf + 2;strcpy(p2,fileName);char *p3 = p2+strlen(p2)+1;strcpy(p3,"octet"); int size = 4+strlen(p2)+strlen(p3); //整体长度//先发送上传请求到服务器if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto error");return -1;}printf("请求成功!\n");socklen_t socklen = sizeof(sin);int n = 1;while(1){bzero(buf,sizeof(buf));recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&socklen);int res = read(fd,buf+4,sizeof(buf)-4); //将文件的512位写入数据包buf[1]=3; //将操作码改为3,即数据包//将buf发送,因为操作码已经修改,发回去数据加上了操作码和块编号sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));if(res==0) //证明已经上传完成,关闭循环break;}printf("上传完成\n");close(fd); //关闭文件}
int main(int argc, const char *argv[])
{if(argc != 2){printf("input error");return -1;}//创建套接字int cfd = socket(AF_INET,SOCK_DGRAM,0);if(cfd == -1){perror("socket error");return -1;}//填充服务器结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(69);sin.sin_addr.s_addr = inet_addr(argv[1]);int key = 0;while(1){system("clear");printf("\t\t菜单\t\t\n");printf("\t\t1.下载\t\t\n");printf("\t\t2.上传\t\t\n");printf("\t\t0.关闭\t\t\n");printf("请输入选项:");scanf("%d",&key);getchar();switch(key){case 1:{//下载int A =download(cfd,sin);};break;case 2:{//上传int B =upload(cfd,sin);};break;case 0:{goto A;};break;default:printf("请输入正确的选项!\n");}//阻塞printf("输入任意键,按回车清空");while(getchar() != '\n');}A:close(cfd);return 0;
}
上传文件
下载文件