#include <myhead.h>
#define SER_PORT 69
#define SER_IP "192.168.0.149"
#define CLI_PORT 5555
#define CLI_IP "192.168.0.150"
int main(int argc,const char *argv[])
{
//1.创建用于通信的服务器套接字文件描述符
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd==-1)
{
perror("socket error");
return -1;
}
int menu = 0;
while(1)
{
printf("****************\n");
printf("****1.下载*******\n");
printf("****2.上传*******\n");
printf("****3.退出*******\n");
printf("****************\n");
printf("请输入>>>");
scanf("%d",&menu);
getchar();
if(menu==1)
{
char buf[516]="";
struct sockaddr_in sin;
socklen_t addrlen = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
char filename[128]="";
printf("请输入要下载的文件名>>>");
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]=0;
//发送下载请求
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 = 2+strlen(p2)+strlen(p3)+2;
sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin));
//打开或创建下载文件
int fd = open(filename,O_WRONLY|O_CREAT,0644);
if(fd==-1)
{
perror("open error");
return -1;
}
while(1)
{
//接收服务器发来的信息
ssize_t n = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,&addrlen);
//判断是否为数据包
short *p4 = (short *)buf;
if(ntohs(*p4)==3)
{
//将收到的数据写入文件
write(fd,buf+4,n-4);
//向服务器发送ACK包
*p4 = htons(4);
sendto(cfd,buf,4,0,(struct sockaddr *)&sin,addrlen);
//判断发来的数据是否小于516,小于表示数据已经传完了
if(n<516)
{
printf("下载成功\n");
break;
}
}
}
}
else if(menu==2)
{
char buf[516]="";
struct sockaddr_in sin;
//socklen_t addrlen = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
char filename[128]="";
printf("请输入要上传的文件名>>>");
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]=0;
//发送上传请求
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 = 2+strlen(p2)+strlen(p3)+2;
sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin));
//打开上传的文件
int fd = open(filename,O_RDONLY);
if(fd==-1)
{
perror("open error");
return -1;
}
//定义传递时的编号
short x=1;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
while(1)
{
memset(buf,0,sizeof(buf));
//封装数据并发送给服务器
short *q1 = (short *)buf;
*q1 = htons(3);
short *q2 = p1+1;
*q2 = htons(x);
ssize_t n = read(fd,buf+4,512);
sendto(cfd,buf,n+4,0,(struct sockaddr *)&addr,sizeof(addr));
//接收服务器发来的数据
memset(buf,0,sizeof(buf));
recvfrom(cfd,buf,4,0,(struct sockaddr *)&addr,&addrlen);
//判断发来的是ACK包并且编号正确
if(ntohs(*q2)==x && ntohs(*q1)==4)
{
//判断文件有没有读取完毕
if(n<512)
{
printf("上传成功\n");
break;
}
x++; //编号加1,然后进行下一次发送
}
else if(ntohs(*q2)!=x && ntohs(*q1)==4)
{
//将光标移动到这一次读取之前
lseek(fd,-n,SEEK_CUR);
}
}
}
else if(menu==3)
{
break;
}
}
close(cfd);
return 0;
}
基于UDP的TFTP文件传输
最新推荐文章于 2024-08-14 17:42:59 发布