#include<myhead.h>
#define SER_IP "192.168.0.158"
#define SER_PORT 69
int do_download(int cfd,struct sockaddr_in sin)
{
char filename[20]="";
char buff[516]={0};
printf("输入要下载的文件名 ");
scanf("%s",filename);
short *p1=(short *)buff;
*p1=htons(1);//下载,操作码
char *p2=buff+2;//文件名地址
scanf("%s",filename);
strcpy(p2,filename);
char *p3=p2+strlen(p2);
*p3=0;
char *p4=p3+1;
strcpy(p4,"octet");
char *p5=p4+strlen(p4);
*p5=0;
int size=2+strlen(p2)+1+strlen(p4)+1;
if(sendto(cfd,buff,size,0,(struct sockaddr *)&sin,sizeof(sin))==-1)
{
perror("sendto");
return -1;
}
printf("sendto success\n");
/*
打开一个文件,用于存储数据
循环接收数据包recvfrom
从数据包中提取数据,存储到文件中
回复应答包sendto
直到数据大小小于512字节,结束循环,下载完成
*/
int fd;
int flag=0;
socklen_t addrlen=sizeof(sin);
ssize_t res=0;
unsigned short num=0;
while(1)
{
bzero(buff,sizeof(buff));
res=recvfrom(cfd,buff,sizeof(buff),0,(struct sockaddr *)&sin,&addrlen);
if(res<0)
{
perror("recvfrom");
return -1;
}
if(3==buff[1])
{
if(htons(num+1)==*(unsigned short *)(buff+2));
{
num++;
if(0==flag)
{
fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd<0)
{
perror("open");
return -1;
}
flag=1;
}
if(write(fd,buff+4,res-4)<0)//参数1文件描述符参数2地址参数3文件大小(字节数) buff+4是因为数据包前面有操作码和快编号
{
perror("write");
return -1;
}
buff[1]=4;
if(sendto(cfd,buff,4,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("sendto");
return -1;
}
if(res-4<512)
{
printf("文件下载成功");
break;
}
}
}
else if(5==buff[1])
{
fprintf(stderr,"errcode=%d errmsg=%s\n",ntohs(*(short *)(buff+2)),buff+4);
return -1;
}
}
close(fd);
return 0;
}
int do_upload(int cfd,struct sockaddr_in sin)
{
char filename[20]="";
char buff[516]="";
printf("输入要上传的文件名0");
scanf("%s",filename);
unsigned short *p1=(short *)buff;
*p1=htons(2);
char *p2=buff+2;
strcpy(p2,filename);
char *p3=p2+strlen(p2);
*p3=0;
char *p4=p3+1;
strcpy(p4,"octet");
size_t size=2+strlen(p2)+1+strlen(p4)+1;
if(sendto(cfd,buff,sizeof(buff),0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("sendto");
return -1;
}
socklen_t addrlen=sizeof(sin);
ssize_t res=0;
unsigned short num=0;
int fd=open(filename,O_RDONLY);
if(fd<0)
{
fprintf(stderr,"文件不存在\n");
return -1;
}
while(1)
{
res=recvfrom(cfd,buff,sizeof(buff),0,(struct sockaddr *)&sin,&addrlen);
if(res==4)
{
if(buff[1]==4)
{
if(htons(num)==*(short*)(buff+2))
{
num++;
printf("接受应答包%d %d\n",__LINE__,ntohs(*(short*)(buff+2)));
}
}
else
{
fprintf(stderr,"接受错误\n");
return -1;
}
}
else if(buff[1]=5)
{
printf("错误 %d %s\n",ntohs(*(short *)(buff+2)),buff+4);
close(fd);
return -1;
}
else if(res<0)
{
perror("recvfrom");
return -1;
}
bzero(buff+4,512);
ssize_t size_r=read(fd,buff+4,512);
buff[1]=3;
*(unsigned short *)(buff+2)=htons(num);
res=sendto(cfd,buff,size_r+4,0,(struct sockaddr *)&sin,addrlen);
if(res<0)
{
perror("sendto");
return -1;
}
if(size_r<512)break;
}
close(fd);
return 0;
}
int main(int argc, const char *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);
int c=0;
while(1)
{
printf("下载输入1\n");
printf("上传输入2\n");
printf("退出输入3\n");
printf("输入数字---");
scanf("%d",&c);
switch(c)
{
case 1:
do_download(cfd,sin);
break;
case 2:
do_upload(cfd,sin);
break;
case 3:
break;
default:
printf("输入错误,请重新输入\n");
}
}
close(cfd);
return 0;
}