代码如下:
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <arpa/inet.h>
5 #include <netinet/in.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <stdlib.h>
11
12 #define ERR_MSG(msg) do{\
13 fprintf(stderr, "line:%d\n", __LINE__);\
14 perror(msg);\
15 }while(0)
16
17 #define IP "192.168.8.105"
18 #define PORT 69
19
20 int download(int sfd, struct sockaddr_in sin);
21 int upload(int sfd, struct sockaddr_in sin);
22
23
24 int main(int argc, const char *argv[])
25 {
26 //创建报时套接字
27 int sfd = socket(AF_INET,SOCK_DGRAM,0);
28 if(sfd<0)
29 {
30 ERR_MSG("socket");
31 return -1;
32 }
33
34 //填充服务器自身的地址信息
35 struct sockaddr_in sin;
36 sin.sin_family = AF_INET;
37 sin.sin_port = htons(PORT);
38 sin.sin_addr.s_addr = inet_addr(IP);
39
40 char choose=0;
41 while(1)
42 {
43 printf("****************************\n");
44 printf("******1.download************\n");
45 printf("******2.upload**************\n");
46 printf("******3.exit****************\n");
47 printf("****************************\n");
48 printf("请输入>>>");
49 choose = getchar();
50 while(getchar()!=10);
51
52 switch(choose)
53 {
54 case '1':
55 download(sfd, sin);
56 break;
57 case '2':
58 upload(sfd, sin);
59 break;
60 case '3':
61 goto END;
62 }
63
64 }
65
66 END:
67 return 0;
68 }
69
70 int upload(int sfd, struct sockaddr_in sin)
71 {
72 char buf[600] = "";
73 ssize_t res = 0;
74
75 char filename[20] = "";
76 printf("请输入要上传的文件名>>>");
77 scanf("%s", filename);
78 while(getchar()!=10);
79
80 //判断文件是否存在
81 int fd = open(filename, O_RDONLY);
82 if(fd < 0)
83 {
84 ERR_MSG("open");
85 return -1;
86 }
87
88 int size = sprintf(buf, "%c%c%s%c%s%c", 0, 2, filename, 0, "octet", 0);
89
90 //发送上传请求
91 if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
92 {
93 ERR_MSG("sendto");
94 return -1;
95 }
96
97 socklen_t addrlen = sizeof(sin);
98 while(1)
99 {
100 bzero(buf, sizeof(buf));
101 //接收数据包
102 res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
103 if(res < 0)
104 {
105 ERR_MSG("recvfrom");
106 return -1;
107 }
108 printf("buf[0]:%d buf[1]:%d 操作码:%#x 快编号:%d\n", \
109 buf[0], buf[1], ntohs(*(short*)buf), ntohs(*(short*)(buf+2)));
110
111 //解析数据包
112 int code = ntohs(*(short*)buf);
113 int num = ntohs(*(short*)(buf+2));
114
115 if(4 == code)
116 {
117 bzero(buf, sizeof(buf));
118
119 //组数据包
120 *(short*)buf = htons(3);
121 *(short*)(buf+2) = htons(num+1);
122
123 res = read(fd, buf+4, 512);
124 if(res < 0)
125 {
126 ERR_MSG("write");
127 return -1;
128 }
129
130 //上传文件
131 if(sendto(sfd, buf, res+4, 0, (struct sockaddr*)&sin, addrlen) < 0)
132 {
133 ERR_MSG("sendto");
134 return -1;
135 }
136 if(res < 512)
137 {
138 printf("文件上传成功\n");
139 break;
140 }
141 }
142
143 }
144
145 return 0;
146 }
147
148
149 int download(int sfd, struct sockaddr_in sin)
150 {
151 //发送下载请求
152 char buf[600] = "";
153 ssize_t res = 0;
154 char filename[20] = "";
155
156 printf("请输入要下载的文件名>>>");
157 scanf("%s", filename);
158 while(getchar()!=10);
159
160 int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);
161
162 //发送下载协议
163 if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
164 {
165 ERR_MSG("sendto");
166 return -1;
167 }
168
169 //打开一个文件,用于存储下载到的数据
170 int fd=-1, flag = 0;
171
172 socklen_t addrlen = sizeof(sin);
173 unsigned short num = 0;
174 while(1)
175 {
176 bzero(buf, sizeof(buf));
177 //接收数据包
178 res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
179 if(res < 0)
180 {
181 ERR_MSG("recvfrom");
182 return -1;
183 }
184
185 if(3 == buf[1]) {
186 if(0 == flag)
187 {
188 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
189 if(fd < 0)
190 {
191 ERR_MSG("open");
192 return -1;
193 }
194 flag = 1;
195 }
196
197
198 if(htons(num+1) == *(unsigned short*)(buf+2))
199 {
200 if(write(fd, buf+4, res-4) < 0)
201 {
202 ERR_MSG("write");
203 break;
204 }
205
206 //回复ACK
207 buf[1] = 4;
208 if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
209 {
210 ERR_MSG("sendto");
211 break;
212 }
213
214 //判断数据是否<512
215 if(res-4 < 512)
216 {
217 printf("文件 %s 下载完毕\n", filename);
218 break;
219 }
220
221 num++;
222 }
223 }
224 else if(5 == buf[1])
225 {
226 printf("ERROR: %d %s\n", ntohs(*(short*)(buf+2)), buf+4);
227 break;
228 }
229 }
230
231 close(fd);
232 return 0;
233 }
234
235
~
~
~
结果如图: