创建tftp客户端
![](https://i-blog.csdnimg.cn/blog_migrate/03ee7f23162af0aa6ee1b18f52465f51.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a69ba45edebb63e8b6154c244fd75a7d.png)
tftp协议
![](https://i-blog.csdnimg.cn/blog_migrate/713036a14a6211cb7a529463903e15f3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e6a9fe528cd9305c13e69f50c6d951e5.png)
创建tftp客户端
1 #include <myhead.h>
2 #define PORT 69
3 #define IP "192.168.124.51"
4
5 void do_download(int cfd,struct sockaddr_in sin);
6 int main(int argc, const char *argv[])
7 {
8
9 int cfd = socket(AF_INET,SOCK_DGRAM,0);
0 if(cfd<0)
1 {
2 ERR_MSG("socket");
3 return -1;
4
5 }
6
7 //绑定服务器
8 struct sockaddr_in sin;
9 sin.sin_family = AF_INET;
0 sin.sin_port =htons(PORT);//端口号的网络字节序
1 sin.sin_addr.s_addr = inet_addr(IP);//本机IP的网络字节序
2 socklen_t sinaddrlen = sizeof(sin);
3
4 char buf[128]="";
5 ssize_t res = 0;
6
7 //接收信息数据包从哪里来
8 struct sockaddr_in rcvaddr;
9 socklen_t addrlen = sizeof(rcvaddr);
0
1 char choose = 0;
2 while(1)
3 {
4 printf("-------------------------------\n");
5 printf("----------1、下载--------------\n");
6 printf("----------2、上传--------------\n");
7 printf("----------3、退出--------------\n");
8 printf("-------------------------------\n");
9 printf("请输入\n");
0 choose = getchar();
1 while(getchar() != '\n');//循环吸收垃圾字符,直到遇到\n
2
3 switch(choose)
4 {
5 case '1':
6 do_download(cfd,sin);
7 break;
8 case '2':
9 //do_upload();
0 break;
1 case '3':
2 goto END;
3 default:
4 printf("输入错误,请重新输入\n");
5 }
6 }
7
8
9 END:
0
1 //关闭
2 close(cfd);
3
4 return 0;
5 }
6 //上传
7 void do_download(int cfd,struct sockaddr_in sin)
8 {
9
0
1 //组ack包
2 char ack[4]="";
3 short* ackp =(short*)ack;
4 *ackp = htons(4);
5
6
7
8 //组下载请求包
9 char buf[512] = "";
0
1 short* ptr1 = (short*)buf;
2 *ptr1 = htons(1);
3
4 char filename[20];
5 printf("请输入文件名\n");
6 scanf("%s",filename);
7 while(getchar() != 10);//换行
8
9 char* ptr2 = buf+2;
0 strcpy(ptr2,filename);
1
2 char* ptr3 = ptr2+strlen(ptr2);
3 *ptr3 = 0;
4
5 char* ptr4 = ptr3+1;
6 strcpy(ptr4,"octet");
7
8
9 //发送下载请求给tftp服务器,sendto
0 int size = 2+strlen(ptr2)+1+strlen(ptr4)+1;
1 if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) <0 )
2 {
3 ERR_MSG("sendto");
4 return;
5 }
6 printf("发送下载请求成功\n");
7
8 //打开要下载的文件
9 int fd = open(filename,O_WRONLY|O_CREAT|,0664);
0 if(fd <0 )
1 {
2 ERR_MSG("open");
3 return -1;
4 }
5
6 ssize_t rcvres =0;
7 while(1)
8 {
9
0 //接收服务器传回来的数据bao
1 if(rcvres = recvfrom(cfd,buf,size,0,(struct sockaddr*)&rcvaddr,&addrlen) < 0)
2 {
3 ERR_MSG("recvfrom");
4 return -1;
5 }
6 printf("接收服务器传回来的数据包成功:%s\n",buf);
7
8
9 //接收的不是数据包
0 if(*ptr1 != htons(3))
1 {
2 continue;
3
4 }
5 //收到的数据写入fd
6 if(write(fd,buf +4,rcvres-4)<0)
7 {
8 ERR_MSG("write");
9 return -1;
0 }
1
2 //发送应答到服务器ack包 sendto
3 if(sendto(cfd,ack,4,0,(struct sockaddr*)rcvaddr,&addrlen)<0)
4 {
5 ERR_MSG("sendto");
6 return -1;
7
8 }
9
0
1 //直到数据长度小于512字节,退出循环
2 if(rcvres < 516)
3 {
4 printf("donwnload finsh\n");
5 break;
6
7 }
8 }
9
0
1 close(fd);
2 }