11.21

#include <myhead.h>
#define IP "192.168.115.180"
int do_download(int cfd,struct sockaddr_in sin)
{
	char buf[516]="";
	char Filename[20]="";
	printf("请输入要下载的文件名: ");
	scanf("%s",Filename);
	//组装请求包
	short *p1=(short *)buf;//操作码
	*p1=htons(1);
	char *p2=buf+2;//文件名
	strcpy(p2,Filename);
	char *p3=p2+strlen(p2)+1;//模式
	strcpy(p3,"octet");
	int len=strlen(p2)+strlen(p3)+4;//操作码+文件名+0+模式+0
	//发送下载请求
	if(sendto(cfd,buf,len,0,(struct sockaddr *)&sin,sizeof(sin))==-1)
	{
		perror("sendto error");
		return -1;
	}
	printf("请求成功\n");
	//定义文件描述符
	int fd=-1;
	socklen_t socklen=sizeof(sin);
	int res=0;
	short n=0;
	while(1)
	{
		bzero(buf,sizeof(buf));

		if((res=recvfrom(cfd,buf,len,0,(struct sockaddr *)&sin,&socklen))==-1)
		{
			perror("recv error");
			return -1;

		}
		if(buf[1]==3)
		{
			//判断服务器返回的数据包的块编号是否一样
			if(*(short *)(buf+2) == htons(n+1))
			{
				//块设备编号
				n++;
				if((fd=open("Filename",O_WRONLY|O_CREAT|O_TRUNC,0664))==-1)
				{
					perror("open error");
					return -1;
				}
			}
			write(fd,buf,res-4);
			//发送ACK
			*p1=htons(4);
			if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
			{
				perror("sendto error");
				return -1;
			}
			//下载完成
			if(res-4 < 512)
			{
				printf("%s 下载完成\n",Filename);
				break;
			}
		}
		else if(5 == buf[1])   
		{
			printf("error %d %s\n",ntohs(*(short*)(buf+2)),buf+4);
			close(fd);
			return -1;
		}
	}
	//关闭文件
	close(fd);
	return 0;
}
int do_upload(int cfd,struct sockaddr_in sin)
{
	char buf[516]="";
	char Filename[20]="";
	printf("请输入要上传的文件名: ");
	scanf("%s",Filename);
	int fd=-1;
	if((fd=open("Filename",O_RDONLY))==-1)
	{
		perror("open error");
		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 len=strlen(p2)+strlen(p3)+4;//操作码+文件名+0+模式+0
	//发送上传请求
	if(sendto(cfd,buf,len,0,(struct sockaddr *)&sin,sizeof(sin))==-1)
	{
		perror("sendto error");
		return -1;
	}
	printf("请求成功\n");
	socklen_t socklen=sizeof(sin);
	int res=0;
	short n=1;
	while(1)
	{
		bzero(buf,sizeof(buf));
		if((res=recvfrom(cfd,buf,len,0,(struct sockaddr *)&sin,&socklen))==-1)
		{
			perror("recv error");
			return -1;
		}
		if(buf[1]==4)
		{
			//块设备编号是否为0
			if(n == ntohs(*(short*)(buf+2)))
			{
				//修改操作码为数据包
				buf[1] = 3;
				//块编号
				n++;
				*(short*)(buf+2) = htons(n);
				//读取数据
				res = read(fd,buf+4,sizeof(buf)-4);
				if(res < 0)
				{
					perror("read error");
					return -1;
				}
				else if(res==0)
				{
					printf("文件上传成功\n");
					break;
				}

				//发送数据包
				if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))==-1)
				{
					perror("sendto error");
					return -1;
				}
			}
			else
			{
				printf("文件上传失败\n");
				break;
			}
		}
		else if(5 == buf[1])   
		{
			printf("error %d %s\n",ntohs(*(short*)(buf+2)),buf+4);
			close(fd);
			return -1;
		}
		//关闭文件
		close(fd);
		return 0;
	}
}
int main(int argc, const char *argv[])
{
	/*
	   if(argc!=2)
	   {
	   printf("input error\n");
	   printf("Usage:./a.out IP\n");
	   return -1;
	   }
	   */
	int menu;
	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(69);
	sin.sin_addr.s_addr=inet_addr(IP);
	if(bind(cfd,(struct sockaddr *)&sin,sizeof(sin))==-1)
	{
		perror("bind error");
		return -1;
	}
	while(1)
	{
		system("clear");
		printf("\t\t===============1、下载==============\n");
		printf("\t\t===============2、上传==============\n");
		printf("\t\t===============0、退出==============\n");
		printf("Please enter menu");
		scanf("%d",&menu);
		switch(menu)
		{
		case 1:{
				   do_download(cfd,sin);
			   }
			   break;
		case 2:{
				   do_upload(cfd,sin);
			   }
			   break;
		case 0:{
				   goto POS;
			   }
		default:printf("input error\n");
		}
POS:
		printf("请输入回车继续\n");
		while(getchar()!='\n');
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值