代码段
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
11 #define ERR_MSG(msg) do{\
12 fprintf(stderr, "line:%d ", __LINE__);\
13 perror(msg);\
14 }while(0)
15
16 #define DIRNAME "5.png"
17 #define PORT 69 //1024~49151
18 #define IP "192.168.31.201" //IP地址,本机IP ifconfig
19
20 int main(int argc, const char *argv[])
21 {
22 //创建报式套接字
23 int sfd = socket(AF_INET, SOCK_DGRAM, 0);
24 if(sfd < 0)
25 {
26 ERR_MSG("socket");
27 return -1;
28 }
29 printf("socket create success sfd=%d __%d__\n", sfd, __LINE__);
30
31
32 //允许端口快速被复用
33
34 //填充服务器的地址信息结构体 AF_INET : man 7 IP
35 struct sockaddr_in sin;
36 sin.sin_family = AF_INET; //必须填AF_INET;
37 sin.sin_port = htons(PORT); //服务器绑定的端口,网络字节序
38 sin.sin_addr.s_addr = inet_addr(IP); //服务器的IP ifconfig
39
40 //数据包最大为操作码+块编号+数据 = 2+2+512 = 516 bytes
41 char buf[516] = "";
42
43 //发送下载请求
44 //组tftp协议包
45 int size = sprintf(buf,"%c%c%s%c%s%c",0,1,DIRNAME,0,"octet",0);
46
47 //发送协议包
48 if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
49 {
50 ERR_MSG("bind");
51 return -1;
52 }
53
54 //创建文件用于接收文件
55 int fd=open(DIRNAME,O_WRONLY|O_CREAT|O_TRUNC,0775);
56
57 //循环接收数据包
58 ssize_t res = 0;
59 ssize_t flag = 0;
60 socklen_t addrlen = sizeof(sin);
61 struct sockaddr_in rcvAddr; //存储获取到的数据包是从谁那里来的
62 unsigned short tt=0;
63 while(1)
64 {
65 bzero(buf, sizeof(buf));
66
67 //收数据包
68 res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
69 if(res < 0)
70 {
71 ERR_MSG("recvfrom");
72 return -1;
73 }
74
75 //判断是否成功接受数据包
76
77 if(buf[1] == 3)
78 {
79 if(htons(tt+1) == *(unsigned short*)(buf+2))
80 {
81 tt++;
82 //将数据写入到文件中
83 flag=write(fd,buf+4,res-4);
84 if(flag < 0)
85 {
86 ERR_MSG("write");
87 return -1;
88 }
89
90
91 short a = (short)buf[2];
92 //ACK 返回操作码以及块编号
93 buf[1] = 4;
94
95 if(sendto(sfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
96 {
97 ERR_MSG("sendto");
98 return -1;
99 }
100
101
102 }
103 if(res < 516)
104 {
105 printf("文件信息接收完毕\n");
106 return -1;
107 }
108 }
109
110 else if(buf[1] == 5)
111 {
112 printf("错误码:code:[%c]\tmsg[%s]\n",*(unsigned short*)(buf+2),buf+4);
113 }
114 flag = 0;
115 }
116
117 //关闭所有文件描述符
118 close(sfd);
119 return 0;
120 }
运行结果
ubuntu@ubuntu:udp$ gcc udpfwd.c
ubuntu@ubuntu:udp$ ./a.out
socket create success sfd=3 __29__
文件信息接收完毕
ubuntu@ubuntu:udp$ eog 5.png