1、基于UDP的TFTP文件传输
#include <allhead.h>
int download(int cfd,struct sockaddr_in sin)
{
char buf[516]=""; //定义资源包
char filename[128]="";
printf("请输入文件名:");
scanf("%s",filename);
while(getchar()!=10);
//打开文件
int fd = -1;
printf("%s\n",filename);
if((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1)
{
perror("open");
return -1;
}
//组装请求包
short* p1 = (short*)buf;
*p1 = htons(1);
char* p2 = buf+2;
strcpy(p2,filename);
char* p3 = p2+strlen(p2)+1;
strcpy(p3,"octet");
int size = 4+strlen(p2)+strlen(p3);
//发送下载请求包到服务器
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("sendto");
return -1;
}
printf("请求成功\n");
socklen_t socklen = sizeof(sin);
char* p5 = buf+4;
while(1)
{
memset(buf,0,sizeof(buf));
int res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
short a = ntohs(*(short*)buf);
short b = ntohs(*(short*)(buf+2));
//printf("%d\n %d\n",a,b);
if(a == 3) //表明是数据包
{
write(fd,p5,res-4);
*p1=htons(4); //修改操作码来代替ACK返回
sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));
}else if(a==5)
{
printf("%s\n",p5);
return -1;
}
if(res<516){break;} //当接收到的字节数小于516说明已经接收完成,跳出循环
}
printf("下载完成!\n");
close(fd);
}
int upload(int cfd,struct sockaddr_in sin)
{
char buf[516]=""; //定义资源包
char filename[128]="";
printf("请输入文件名:");
scanf("%s",filename);
while(getchar()!=10);
//打开文件
int fd = -1;
if((fd = open(filename,O_RDONLY)) == -1)
{
perror("open");
return -1;
}
//组装请求包
short* p1 = (short*)buf;
*p1 = htons(2);
char* p2 = buf+2;
strcpy(p2,filename);
char* p3 = p2+strlen(p2)+1;
strcpy(p3,"octet");
int size = 4+strlen(p2)+strlen(p3);
//发送上传请求包到服务器
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("sendto");
return -1;
}
printf("请求成功\n");
socklen_t socklen = sizeof(sin);
int n=0;
while(1)
{
memset(buf,0,sizeof(buf));
recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&socklen);
int res = read(fd,buf+4,512);//将文件读入buf的数据域中
//printf("%d\n",res);
*p1=htons(3); //修改操作码为3 作为数据包进行传输
n++;
*(short*)(buf+2)=htons(n);
//printf("%d\n",n);
//发送buf到服务器
sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
if(res == 0){break;}//当read返回值为0时表示数据已经读取完毕
}
printf("上传完成!\n");
close(fd);
}
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("请输入IP地址\n");
return -1;
}
//1、创建用于通信的套接字文件描述符
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd == -1)
{
perror("socket");
return -1;
}
//3、消息收发
//3.1定义一个地址信息结构体接收客户端地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(69);
sin.sin_addr.s_addr = inet_addr(argv[1]);
//界面设计
printf("\033[01;33;10m>>>>>>>文件管理器<<<<<<<\n");
printf("\033[01;34;10m>>>>>>>1.上传<<<<<<<\n");
printf(">>>>>>>2.下载<<<<<<<\n");
printf(">>>>>>>3.退出<<<<<<<\n");
int Down,Up;
while(1)
{
printf("\033[01;32;10m请选择:\033[0m");
int sel;
scanf("%d",&sel);
switch(sel)
{
case 2: //下载
Down = download(cfd,sin);
break;
case 1: //上传
Up = upload(cfd,sin);
break;
case 3:
return 0;
default:
printf("请输入正确选项!\n");
}
}
close(cfd);
return 0;
}