11.20 作业

#include 
//实现下载功能
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);

	//向服务器发送下载请求
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){
		perror("sendto error");
		return -1;
	}
	printf("请求成功\n");

	socklen_t socklen = sizeof(sin);

	//循环接收回复服务器发来的消息
	//组装数据包
	//打开文件
	int fd = -1;
	if((fd = open(fileName,O_RDWR|O_TRUNC|O_CREAT,0666)) < 0){
		perror("open error");
		return -1;
	}
	while(1){
		//接收数据包
		bzero(buf,sizeof(buf));
		int res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
		if(res < 0){
			perror("recvfrom error");
			return -1;
		}
		//判断操作码
		if(buf[1] == 3){
			//写入文件
			if(write(fd,buf+4,res-4) < 0){
				perror("write error");
				return -1;
			}
			//构造ACK
			buf[1] = 4;
			//发送ACK
			if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) <0){
				perror("sendto error");
				return -1;
			}
			//判断数据包数据大小
			if(res - 4<512){
				printf("%s 下载完成\n",fileName);
				break;
			}
		}else if(buf[1] == 5){
			printf("%d %s\n",ntohs(*(short*)(buf+2)),buf+4);
			break;
		}
	}
	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 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(argv[1]);

	int mune = -1;
	while(1){
		system("clear");        //清屏
		printf("\t\t=====1.下载=====\n");
		printf("\t\t=====2.上传=====\n");
		printf("\t\t=====0.退出=====\n");

		printf("请输入功能:");
		scanf("%d",&mune);
		getchar();

		//多分支选择
		switch(mune){
			case 1:{
				   	do_download(cfd,sin);
				   }
				   break;
			case 2:{
				   	//do_upload();
				   }
				   break;
			case 0:
				   goto POS;
			default:printf("输入功能有误,请重新输入\n");
		}
		//阻塞
		printf("输入任意键,按回车清空:");
		while(getchar() != '\n');
	}
POS:
	//关闭套接字
	close(cfd);
	return 0;
}

11.20 作业_第1张图片

你可能感兴趣的:(linux)