上传下载
#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); //要发送的数据的大小
socklen_t socklen=sizeof(sin);
//向服务器发送下载请求
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("sendto error");
return -1;
}
printf("请求成功\n");
int wfd=-1;
if((wfd=open(fileName,O_RDWR|O_CREAT|O_APPEND|O_TRUNC,0664))==-1)
{
perror("open error");
return -1;
}
while(1)
{
bzero(buf,sizeof(buf));
if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen)==-1)
{
perror("recvfrom error");
return -1;
}
short *q1=(short *)buf; //数据包
short *q2=q1+2; //块编号
char *q3=buf+4; //数据
write(wfd,q3,strlen(q3));
if(strlen(q3)<=0) //没有数据
{
break;
}
//有数据,将ACK返回发送到服务器
bzero(buf,sizeof(buf));
//组装ACK
short *k1=(short *)buf; //操作码
*k1=htons(4);
short *k2=k1+2; //块编号
*k2=*q2;
if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("sendto error");
return -1;
}
}
}
//自定义上传函数
int do_upload(int cfd,struct sockaddr_in sin)
{
//定义一个变量存储上传请求包
char buf[516]="";
//定义变量存储文件名
char fileName[40]="";
printf("请输入要上传的文件名:");
scanf("%s",fileName);
//组装请求包
short *p1=(short *)buf;
*p1=htons(2); //表明要上传
char *p2=buf+2;
strcpy(p2,fileName);
char *p4=p2+strlen(p2)+1;
strcpy(p4,"octet");
int size=4+strlen(p2)+strlen(p4); //要上传的总字节大小
socklen_t socklen=sizeof(sin);
//向服务器发送上传请求
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("sendto error");
return -1;
}
printf("请求成功\n");
int rfd=-1;
if((rfd=open(fileName,O_RDONLY))==-1)
{
perror("open error");
return -1;
}
//循环接收服务器发来的消息
while(1)
{
bzero(buf,sizeof(buf));
if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen)==-1)
{
perror("recvfrom error");
return -1;
}
short *q1=(short *)buf; //操作码
*q1=htons(4);
short *q2=q1+2; //块编号
bzero(buf,sizeof(buf));
short *k1=(short *)buf;
*k1=htons(3);
short *k2=k1+2;
*k2=*q2;
char *k3=buf+4;
read(rfd,k3,strlen(k3));
if(strlen(k3)<=0)
{
break;
}
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("sendto error");
return -1;
}
}
}
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; //ipv4
sin.sin_port=htons(69); //端口号
sin.sin_addr.s_addr=inet_addr(argv[1]);
int menu=-1;
while(1)
{
system("clear");
printf("\t\t========1、下载=========\n");
printf("\t\t========2、上传=========\n");
printf("\t\t========0、退出=========\n");
printf("请输入功能选项:");
scanf("%d",&menu);
getchar();
switch(menu)
{
case 1:{
do_download(cfd,sin);
}
break;
case 2:{
do_upload(cfd,sin);
}
break;
case 0:{
goto B;
}
default:printf("您的输入有误,请重新输入\n");
}
printf("输入任意键,按回车清空\n");
while(getchar()!='\n');
}
B:
//关闭套接字
close(cfd);
return 0;
}