基于UDP的TFTP文件传输
代码
#include<myhead.h>
//服务器
#define SER_PORT 69
#define SER_IP "172.16.9.127"
//客户端
#define CLI_PORT 6666
#define CLI_IP "172.16.9.175"
//菜单
void print_menu()
{printf("输入1>>>下载\n");printf("输入2>>>上传\n");printf("输入3>>>退出\n");
}
//下载
void download(int cfd,struct sockaddr_in sin)
{//读写请求的封装//输入文件名存入fileprintf("输入文件名:");char file[10]="";scanf("%s",file);getchar();char buf[516]="";//消息容器short *p1=buf;*p1=htons(1);//操作码char *p2=buf+2;//文件名strcpy(p2,file);char *p4=p2+strlen(p2)+1;//模式strcpy(p4,"octet");int size=2+strlen(p2)+strlen(p4)+2;//总长度//服务器struct sockaddr_in re;socklen_t len=sizeof(re);//发送给服务器sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin));int fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0664);//只写形式创建文件if(fd==-1){perror("open error");return -1;}while(1){bzero(buf,sizeof(buf));//初始化容器int recv=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&re,&len);//接收ackwrite(fd,buf+4,recv-4);//将数据写入文件//修改操作码if(buf[1]==3){buf[1]=4;}sendto(cfd,buf,4,0,(struct sockaddr*)&re,len);//发送数据包//判断接收数据是否小于516if(recv<516){printf("下载成功\n");break;}}close(fd);//关闭文件return ;
}
//上传
void upload(int cfd,struct sockaddr_in sin)
{//读写请求封装//存入文件名printf("输入文件名:");char file[10]="";scanf("%s",file);getchar();char buf[516]="";//消息容器short *p1=buf;*p1=htons(2);//操作码char *p2=buf+2;strcpy(p2,file);//文件名char *p4=p2+strlen(p2)+1;//模式strcpy(p4,"octet");int size=2+strlen(p2)+strlen(p4)+2;//总长度//服务器struct sockaddr_in re;socklen_t len=sizeof(re);sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin));//发送给服务器//只读形式打开文件int fd=open(file,O_RDONLY);if(fd==-1){perror("file error");return ;}while(1){bzero(buf,sizeof(buf));//初始化int recv=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&re,&len);//接收ackbuf[3]++;//块编号加1//修改操作码if(buf[1]=4){buf[1]=3;}int src=read(fd,buf+4,512);//读取文件内容sendto(cfd,buf,src+4,0,(struct sockaddr*)&re,len);//发送//判断读取内容是否小于512if(src<512){printf("上传成功\n");break;}}close(fd);//关闭文件return ;
}int main(int argc, char const *argv[])
{//创建套接字int cfd=socket(AF_INET,SOCK_DGRAM,0);if(cfd==-1){perror("socket error");return -1;}//服务器信息struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP);while(1){print_menu();//打印菜单char c=0;//功能printf("输入功能:");scanf("%c",&c);getchar();//判断功能switch(c){//下载case '1':{download(cfd,sin);}break;//上传case '2':{upload(cfd,sin);}break;//退出case '3':{close(cfd);//关闭套接字return 0;}default:printf("input error\n");}}close(cfd);return 0;
}
运行结果




