网络编程day030829

UDP实现的tftp客户端上传下载
代码
#include<myhead.h>

//do-while只是为了不让花括号单独存在,并不循环
#define ERR_MSG(msg) do{\
	fprintf(stderr,"%d:",__LINE__);\
	perror(msg);\
}while(0);

#define SER_PORT 69//指定要把数据发给谁就填谁的端口号1024-49151
#define SER_IP "192.168.114.46"//指定要将数据发给谁就填谁的IP,终端输入ifconfig可得

int do_download(int cfd,struct sockaddr_in* seraddr,socklen_t seraddrlen);
int do_upload(int cfd,struct sockaddr_in* seraddr,socklen_t seraddrlen);

int main(int argc, const char *argv[])
{
	//创建报式套接字 socket
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd<0){
		ERR_MSG("socket");
		return -1;
	}
	printf("socket create success cfd=%d\n",cfd);

	//填充服务器的地址信息结构体,用于发送
	//真实的地址信息结构体根据地址族制定 AF_INET:man 7 ip
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;//必须填AF_INET
	sin.sin_port   		= htons(SER_PORT);//服务器端口号的网络字节序
	sin.sin_addr.s_addr = inet_addr(SER_IP);//服务器IP
	socklen_t addrlen   = sizeof(sin);

	char choice = 0;
	while(1){
		system("clear");
		printf("******************************\n");
		printf("**********1.下载**************\n");
		printf("**********2.上传**************\n");
		printf("**********3.退出**************\n");
		printf("******************************\n");
		printf("请输入:");
		scanf("%c",&choice);
		while(getchar()!=10);

		int flag = 0;
		switch(choice){
			case '1':
				//下载  do_download
				do_download(cfd,&sin,addrlen);
					break;
			case '2':
				//上传  do_upload
				do_upload(cfd,&sin,addrlen);
				break;
			case '3':
				flag = 1;
				break;
			default:
				printf("输入不规范,亲人两行泪\n");
				break;
		}

		if(1==flag){
			break;
		}

		printf("输入任意字符清屏:");
		while(getchar()!=10);
	}
	
	
	//关闭文件描述符
	close(cfd);

	return 0;
}

int do_download(int cfd,struct sockaddr_in* seraddr,socklen_t seraddrlen){
	char filename[128]="";
	printf("请输入要下载的文件名:");
	scanf("%s",filename);
	while(getchar()!=10);
	
	//组下载请求包
	char buf[516]="";

	unsigned short *ptr1 = (unsigned short*)buf;
	*ptr1 = htons(1);

	char *ptr2 = buf+2;
	strcpy(ptr2,filename);

	char *ptr3 = ptr2+strlen(filename)+1;
	strcpy(ptr3,"octet");

	int size = 2+strlen(ptr2)+1+strlen(ptr3)+1;
	//发送下载请求-->sendto
	if(sendto(cfd, buf, size, 0, (struct sockaddr*)seraddr, seraddrlen)<0){
		ERR_MSG("sendto error");
		return -1;
	}
/*	char mode[] = "octet";
	unsigned short operate = htons(1);
	size_t size = sizeof(operate)+strlen(filename)+sizeof("\0")+sizeof(mode)+sizeof("\0");
	snprintf(loadbag,size,"%d%s\0%s\0",operate,filename,mode);

	//发送下载请求-->sendto
	if(sendto(cfd,loadbag,size,0,(struct sockaddr*)seraddr,seraddrlen)<0){
		ERR_MSG("sendto error");
		return -1;
	}
*/
	int filefd;
	if((filefd=open(filename,O_WRONLY|O_CREAT|O_EXCL|O_TRUNC,0664))==-1){
		if(errno==EEXIST){
			filefd = open(filename,O_WRONLY|O_TRUNC);
			printf("open success\n");
		}else{
			ERR_MSG("open error");
			return -1;
		}
	}
	printf("%d\n",filefd);

	struct sockaddr_in dstaddr;
	socklen_t dstaddrlen;
	ssize_t res;
	//char buf[516];
	char ACKbag[4] = "";
	unsigned short *ptr4 = (unsigned short*)ACKbag;
	unsigned short *ptr5 = ptr4+1;
	unsigned short *ptr6 = (unsigned short*)&buf[2];
	char *ptrbuf = &buf[4];
	while(1){
		bzero(buf,sizeof(buf));
		//接收数据 recvfrom,接收地址信息
		if((res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dstaddr,&dstaddrlen))<0){
			ERR_MSG("recvfrom error");
			return -1;
		}
		if(write(filefd,ptrbuf,sizeof(buf)-4)<0){
			ERR_MSG("write error");
			return -1;
		}
		//组ACK包
		*ptr4 = htons(4);
		*ptr5 = *ptr6;
		size = 4;
		//发送ACK-->sendto
		if(sendto(cfd,ACKbag,size,0,(struct sockaddr*)&dstaddr,dstaddrlen)<0){
			ERR_MSG("sendto error");
			return -1;
		}
		
		//判断数据是否小于512个字节,若小于则下载完成
		if(res<512){
			printf("下载完成\n");
			close(filefd);
			break;
		}
	
	}
	return 0;

}

int do_upload(int cfd,struct sockaddr_in* seraddr,socklen_t seraddrlen){
	char filename[128]="";
	printf("请输入要上传的文件名:");
	scanf("%s",filename);
	while(getchar()!=10);
	
	//组上传请求包
	char buf[516]="";

	unsigned short *ptr1 = (unsigned short*)buf;
	*ptr1 = htons(2);

	char *ptr2 = buf+2;
	strcpy(ptr2,filename);

	char *ptr3 = ptr2+strlen(filename)+1;
	strcpy(ptr3,"octet");

	int size = 2+strlen(ptr2)+1+strlen(ptr3)+1;

	struct sockaddr_in dstaddr;
	socklen_t dstaddrlen;
	int res;
	char ACKbag[4] = "";
	unsigned short *signptr = (unsigned short *)&ACKbag[2]; 
	//如果没有收到服务器的答复就持续申请
	while(1){
		printf("请求中…………\n");
		//发送上传请求-->sendto
		if(sendto(cfd, buf, size, 0, (struct sockaddr*)seraddr, seraddrlen)<0){
			ERR_MSG("sendto error");
			return -1;
		}	
	
		//接收ACK包
		if((res=recvfrom(cfd,ACKbag,sizeof(ACKbag),0,(struct sockaddr*)&dstaddr,&dstaddrlen))<0){
			ERR_MSG("recvfrom error");
			return -1;
		}		
		if(ntohs(0)==*signptr){
			printf("请求成功\n");
			break;
		}
	}

	//打开要被发送的文件
	int filefd;
	if((filefd=open(filename,O_RDONLY))==-1){
		ERR_MSG("open error");
		return -1;
	}
	printf("%d\n",filefd);
	
	ptr2 = buf+4;
	unsigned short *bandsignptr = (unsigned short*)&buf[2];
	unsigned short bandsign = 1;
	//char buf[516];
	while(1){
		bzero(buf,sizeof(buf));
		//组WRQ数据包
		*ptr1 = htons(3);
		*bandsignptr = htons(bandsign);
		if((res=read(filefd,ptr2,512))==-1){
			ERR_MSG("read error");
			return -1;
		}
		while(1){
			//循环发送数据 -->sendto,并且只有当收到返回的ACK包的值正确时才结束循环
			if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dstaddr,dstaddrlen)<0){
				ERR_MSG("recvfrom error");
				return -1;
			}
			if(recvfrom(cfd,ACKbag,sizeof(ACKbag),0,(struct sockaddr*)&dstaddr,&dstaddrlen)<0){
				ERR_MSG("recvfrom error");
				return -1;
			}
			if(ntohs(bandsign)==*signptr){
				break;
			}
		}
		
		//判断数据是否小于512个字节,若小于则下载完成
		if(res<512){
			printf("上传完成\n");
			close(filefd);
			break;
		}

		bandsign++;
	
	}


	return 0;
}









下载效果

下载前:

操作:

结果:

上传效果

上传前:

思维导图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值