天天看點

【LINUX/UNIX網絡程式設計】之使用SOCKET進行UDP程式設計

先看任務需求:

實驗二 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:表示通訊結束,雙方退出。

先畫一下流程圖友善理順思路:

【LINUX/UNIX網絡程式設計】之使用SOCKET進行UDP程式設計
【LINUX/UNIX網絡程式設計】之使用SOCKET進行UDP程式設計
【LINUX/UNIX網絡程式設計】之使用SOCKET進行UDP程式設計

下面上代碼:

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      

代碼寫的挺爛的,裡面有很多重複的代碼和功能,完全可以抽取出來做成一個函數的。以後慢慢再改吧。先完成功能,把上機考試過了再說。

繼續閱讀