1. 基于UDP的TFTP文件传输
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <myhead.h>//实现下载功能
int do_download(int cfd, struct sockaddr_in sin)
{//定义变量存储下载请求包char buf[516] = "";//定义变量存储文件名char fileName[40] = "";printf("请输入文件名:");scanf("%s", fileName);getchar();//组装请求包short *p1 = (short *)buf;*p1 = htons(1); //表明要下载char *p2 = buf+2; //文件名段strcpy(p2, fileName);char *p4 = p2+strlen(p2)+1; //模式段strcpy(p4, "octet");int size = 4 + strlen(p2) + strlen(p4); //要发送数据的大小//向服务器发送下载请求if(sendto(cfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("sendto error");return -1;}printf("请求成功\n");//循环接收回复服务器发来的消息//写文件int fd = -1;//以写的形式打开文件if((fd = open(fileName, O_WRONLY|O_CREAT|O_TRUNC, 0664)) == -1){perror("open error");return -1;}socklen_t len = sizeof(sin);char *p5 = buf+4;while(1){bzero(buf,sizeof(buf));//接收服务器发送的请求int res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&len);if(res == -1){perror("recvfrom error");return -1;}//printf("buf %s\n",buf);int data = buf[1];if(data == 3){ //发数据发送成功//写文件从5位开始if(res < 516){write(fd,p5,res-4);break;}else{write(fd,p5,512);}//发送ackbuf[1] = 4;if(sendto(cfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("sendto error");return -1;}}if(data == 5){printf("error %s\n",p5);return -1;}}printf("下载完成\n");close(fd);}int main(int argc, const char *argv[])
{if(argc != 2){printf("input error\n");printf("usage:./a.out ip\n");return -1;}//1、创建套接字int cfd = socket(AF_INET, SOCK_DGRAM, 0);if(cfd == -1){perror("socket error");return -1;}//2、填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(69);sin.sin_addr.s_addr = inet_addr(argv[1]);int mune = -1;while(1){system("clear"); //清屏printf("\t\t======1、下载=======\n");printf("\t\t======2、上传=======\n");printf("\t\t======0、退出=======\n");printf("请输入功能:");scanf("%d", &mune);getchar();//多分支选择switch(mune){case 1:{do_download(cfd, sin);}break;case 2:{//do_upload();}break;case 0:goto POS;default:printf("输入功能有误,请重新输入\n");}//阻塞printf("输入任意键,按回车清空:");while(getchar() != '\n');}POS://关闭套接字close(cfd);return 0;
}