先看任务需求:
实验二 UDP数据发送与接收
【实验目的】
1、熟练掌握套接字函数的使用方法。
2、应用套接字函数完成基本UDP通讯,实现服务器与客户端的文件传送
【实验学时】
4学时
【实验内容】
要求:
(1)客户可以从服务器下载文件、或向服务器上传文件。
(2)客户可向服务器发送多种指令:DOWNLOAD、UPLOAD、YES、NO、START、END、SHUTDOWN、CONTENT、OKDOWLOAD格式:DOWLOAD [filename]表示从服务器下载filename文件,如果服务器存在该文件,返回YES,否则返回NO;客户接收如果是YES,可发送START表示开始下载,之后,服务器将文件传送给客户,客户接收并保存;UPLOAD格式:UPLOAD [filename]表示向服务器上传filename文件,服务器发送NO表示拒绝接收。服务器发送START表示开始传送,之后向服务器传输文件;END:表示文件传送结束SHUTDOWN:表示通讯结束,双方退出。
先画一下流程图方便理顺思路:
下面上代码:
1.定义了一个protocol结构体方便传输信息和信息校验等;
1 #ifndef _protocol 2 #define _protocol 3 4 #define INFOLEN 1000 5 #define SHUTDOWN 0 6 #define DOWNLOAD 1 7 #define UPLOAD 2 8 #define YES 3 9 #define NO 4 10 #define START 5 11 #define END 6 12 #define CONTENT 7 13 #define OK 8 14 15 struct protocol 16 { 17 int command; 18 int len; //length of buf 19 int no; 20 char buf[INFOLEN]; 21 }; 22 #endif
2.客户端程序:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <sys/types.h> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 #include "protocol.h" 10 11 12 /*-----------------------变量声明区------------------*/ 13 int socketfd; 14 int addrlen; 15 struct sockaddr_in server; 16 struct protocol sentbuf; 17 struct protocol recvbuf; 18 int num; 19 char ip[20]; 20 int port; 21 int choice; 22 char filename[100]; 23 /*------------------------函数声明区------------------*/ 24 void ShowMenu(); 25 void DownLoad(); 26 void UpLoad(); 27 void ShutDown(); 28 29 30 int main() { 31 32 /*-------------create UDP socket------------*/ 33 if((socketfd = socket(AF_INET,SOCK_DGRAM,0)) == -1){ 34 perror("socket error\n"); 35 exit(1); 36 } 37 38 /*-----------------IO-----------------------*/ 39 printf("Please input the ip:\n"); 40 scanf("%s",ip); 41 printf("Please input the port:\n"); 42 scanf("%d",&port); 43 44 /*--------------------recvfrom and sendto----------*/ 45 bzero(&server,sizeof(server)); 46 server.sin_family = AF_INET; 47 server.sin_port = htons(port); 48 server.sin_addr.s_addr = inet_addr(ip); 49 addrlen = sizeof(server); 50 51 /*--------------------调试信息--------------------------- 52 recvbuf.command = DOWNLOAD; 53 recvbuf.no =0; 54 printf("input the message:\n"); 55 scanf("%s",recvbuf.buf); 56 recvbuf.len = strlen(recvbuf.buf); 57 sendto(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,sizeof(server)); */ 58 59 60 while (1){ 61 ShowMenu(); 62 scanf("%d",&choice); 63 if(choice == SHUTDOWN){ 64 ShutDown(); 65 break; 66 } 67 else if(choice == DOWNLOAD){ 68 DownLoad(); 69 } 70 else if(choice == UPLOAD){ 71 UpLoad(); 72 } 73 else{ 74 printf("Please make a right choice!\n"); 75 } 76 } 77 78 /*-----------------close------------------------*/ 79 close(socketfd); 80 return 0; 81 } 82 83 84 void ShowMenu(){ 85 printf("=====================================\n"); 86 printf(" Please make a choice: \n"); 87 printf(" 0: ||shutdown|| \n"); 88 printf(" 1: ||download|| \n"); 89 printf(" 2: || upload || \n"); 90 printf("=====================================\n"); 91 } 92 void DownLoad(){ 93 bzero(&recvbuf,sizeof(recvbuf)); 94 bzero(&sentbuf,sizeof(sentbuf)); 95 bzero(filename,sizeof(filename)); 96 printf("Please input the file name:\n"); 97 scanf("%s",sentbuf.buf); 98 sentbuf.command = DOWNLOAD; 99 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 100 bcopy(sentbuf.buf,filename,strlen(sentbuf.buf)); 101 recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen); 102 if(recvbuf.command == YES){ 103 printf("YES!\n"); 104 printf("Start to transmission!\n"); 105 sentbuf.command = START; 106 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 107 int no =0; 108 int fd =open(filename,O_CREAT | O_TRUNC |O_WRONLY,0644); 109 if(fd < 0){ 110 perror("create file error\n"); 111 exit(1); 112 } 113 bzero(&recvbuf,sizeof(recvbuf)); 114 while((num = recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen)) >0){ 115 if(recvbuf.command == CONTENT){ 116 if(no == recvbuf.no){ 117 write(fd,recvbuf.buf,recvbuf.len); 118 //printf("kkk%s\n",recvbuf.buf ); 119 no++; 120 bzero(&recvbuf,sizeof(recvbuf)); 121 } 122 else{ 123 perror("The file no is not same.Some message is missed! error occured! \n"); 124 break; 125 } 126 } 127 if(recvbuf.command == END){ 128 close(fd); 129 printf("transmission is successful!\n"); 130 break; 131 } 132 } 133 } 134 else if(recvbuf.command ==NO){ 135 perror("NO such file on server!\n"); 136 } 137 else{ 138 perror("recvbuf.command error\n"); 139 exit(1); 140 } 141 } 142 void UpLoad(){ 143 bzero(&recvbuf,sizeof(recvbuf)); 144 bzero(&sentbuf,sizeof(sentbuf)); 145 bzero(filename,sizeof(filename)); 146 printf("Please input the file name:\n"); 147 scanf("%s",sentbuf.buf); 148 sentbuf.command = UPLOAD; 149 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 150 bcopy(sentbuf.buf,filename,strlen(sentbuf.buf)); 151 //判断要传输的文件是否存在 152 int fd; 153 fd = open(filename,O_RDONLY); 154 if(fd < 0){ 155 perror("The file you want to trans is not exist!\n"); 156 exit(1); 157 } 158 recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen); 159 if(recvbuf.command == START){ 160 int no =0; 161 while((num = read(fd,sentbuf.buf,INFOLEN)) >0){ 162 sentbuf.no = no; 163 sentbuf.command = CONTENT; 164 sentbuf.len = strlen(sentbuf.buf); 165 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 166 no++; 167 bzero(&sentbuf,sizeof(sentbuf)); 168 } 169 bzero(&sentbuf,sizeof(sentbuf)); 170 sentbuf.command = END; 171 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 172 } 173 else if(recvbuf.command == NO){ 174 printf("not transmission\n"); 175 printf("The file is exist!\n"); 176 } 177 else { 178 perror("error! wrong choice!\n"); 179 } 180 } 181 182 void ShutDown(){ 183 printf("client is shutdown now!\n"); 184 bzero(&sentbuf,sizeof(sentbuf)); 185 sentbuf.command == SHUTDOWN; 186 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&server,sizeof(server)); 187 }
3.服务器端程序:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <sys/types.h> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 #include "protocol.h" 10 11 /*-----------------------变量声明区------------------*/ 12 int socketfd; 13 int addrlen; 14 struct sockaddr_in server; 15 struct sockaddr_in client; 16 struct protocol sentbuf; 17 struct protocol recvbuf; 18 int num; 19 char ip[20]; 20 int port; 21 int choice; 22 23 int main(){ 24 25 /*-------------create UDP socket------------*/ 26 if((socketfd = socket(AF_INET,SOCK_DGRAM,0)) == -1){ 27 perror("socket error\n"); 28 exit(1); 29 } 30 31 /*-----------------IO-----------------------*/ 32 printf("Please input the ip:\n"); 33 scanf("%s",ip); 34 printf("Please input the port:\n"); 35 scanf("%d",&port); 36 37 /*-----------------bind----------------------*/ 38 bzero(&server,sizeof(server)); 39 server.sin_family = AF_INET; 40 server.sin_port = htons(port); 41 server.sin_addr.s_addr = inet_addr(ip); 42 if (bind(socketfd,(struct sockaddr *)&server,sizeof(server)) == -1){ 43 perror("bind error\n"); 44 exit(1); 45 } 46 47 /*---------------------调试信息------------ 48 addrlen = sizeof(client); 49 recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen); 50 num = strlen(recvbuf.buf); 51 recvbuf.buf[num] = '\0'; 52 printf("command %d\n",recvbuf.command ); 53 printf("len %d\n",recvbuf.len ); 54 printf("no %d\n", recvbuf.no); 55 printf("buf %s\n",recvbuf.buf ); */ 56 57 addrlen = sizeof(client); 58 while(1){ 59 bzero(&recvbuf,sizeof(recvbuf)); 60 num =recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen); 61 choice = recvbuf.command; 62 if(choice == DOWNLOAD){ 63 char buf[100]; 64 int fd; 65 fd = open((recvbuf.buf),O_RDONLY); 66 if(fd <0){ 67 sentbuf.command = NO; 68 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client)); 69 printf("no such file!\n"); 70 exit(1); 71 } 72 else{ 73 sentbuf.command = YES; 74 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client)); 75 recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&client,&addrlen); 76 if(recvbuf.command == START){ 77 int no =0; 78 while((num = read(fd,sentbuf.buf,INFOLEN)) >0){ 79 sentbuf.no = no; 80 sentbuf.command = CONTENT; 81 sentbuf.len = strlen(sentbuf.buf); 82 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client)); 83 no++; 84 bzero(&sentbuf,sizeof(sentbuf)); 85 } 86 bzero(&sentbuf,sizeof(sentbuf)); 87 sentbuf.command = END; 88 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client)); 89 } 90 } 91 } 92 else if(choice == UPLOAD){ 93 int fd1= open(recvbuf.buf,O_RDONLY); 94 if (fd1 < 0){ 95 sentbuf.command = START; 96 } 97 else{ 98 sentbuf.command = NO; 99 } 100 close(fd1); 101 sendto(socketfd,&sentbuf,sizeof(sentbuf),0,(struct sockaddr *)&client,sizeof(client)); 102 if(sentbuf.command ==START){ 103 int no =0; 104 int fd =open(recvbuf.buf,O_CREAT | O_TRUNC |O_WRONLY,0644); 105 if(fd < 0){ 106 perror("create file error\n"); 107 exit(1); 108 } 109 bzero(&recvbuf,sizeof(recvbuf)); 110 while((num = recvfrom(socketfd,&recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&server,&addrlen)) >0){ 111 if(recvbuf.command == CONTENT){ 112 if(no == recvbuf.no){ 113 write(fd,recvbuf.buf,recvbuf.len); 114 //printf("kkk%s\n",recvbuf.buf ); 115 bzero(&recvbuf,sizeof(recvbuf)); 116 } 117 else{ 118 perror("The file no is not same.Some message is missed! error occured! \n"); 119 break; 120 } 121 } 122 if(recvbuf.command == END){ 123 close(fd); 124 printf("transmission is successful!\n"); 125 break; 126 } 127 } 128 } 129 else if(sentbuf.command == NO){ 130 printf("Not to trans the file\n"); 131 printf("The file is exist!\n"); 132 } 133 else{ 134 perror("error! wrong choice!\n"); 135 exit(1); 136 } 137 138 } 139 else if (recvbuf.command == SHUTDOWN){ 140 printf("Now the server is shutdown!\n"); 141 break; 142 } 143 } 144 145 /*----------------------close ----------*/ 146 close(socketfd); 147 return 0; 148 }
4.makefile文件;
1 main:udpserver.o udpclient.o 2 gcc -o udpserver udpserver.o 3 gcc -o udpclient udpclient.o 4 udpserver.o:udpserver.c protocol.h 5 gcc -c udpserver.c 6 udpclient.o: udpclient.c protocol.h 7 gcc -c udpclient.c 8 clean: 9 rm -rf *.o
代码写的挺烂的,里面有很多重复的代码和功能,完全可以抽取出来做成一个函数的。以后慢慢再改吧。先完成功能,把上机考试过了再说。