先看任務需求:
實驗二 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
代碼寫的挺爛的,裡面有很多重複的代碼和功能,完全可以抽取出來做成一個函數的。以後慢慢再改吧。先完成功能,把上機考試過了再說。