网络编程 day3

TFTP通信过程:

#include <myhead.h>

#define SER_PORT  69
#define SER_IP "192.168.125.13"

int do_download(int cfd,struct sockaddr_in sin){

	unsigned short code = 0;
	unsigned short num = 0;
	unsigned char ack1[4] = ""; 
	ssize_t ret = 0;
	char filename[20]="";int size = sprintf(buf,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);

	printf("请输入要下载的文件名:");
	scanf("%s",filename);
	//组下载请求包
	//int size = sprintf(buf,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
	char buf[516]="";
	int fd;
	unsigned short* ptr1 = (unsigned short*)buf;
	*ptr1 = htons(1);

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

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

	int size = 2+strlen(ptr2)+strlen(ptr4)+2;


	//发送下载请求
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0){

		ERR_MSG("sendto");
		return -1;
	}

	socklen_t addrlen = sizeof(sin);
	int flag=0;

	while(1){
		bzero(buf,sizeof(buf));
		//接收数据,接收地址信息
		if(-1 == (ret = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen)))
			ERR_MSG("recvfrom");


		if(3 == buf[1]){

			//创建文件接收数据文件
			if(flag == 0){

				fd=open(filename,O_WRONLY | O_CREAT | O_TRUNC,0664);
				if(fd<0){
					ERR_MSG("fopen");
					return -1;
				}
				flag =1;
			}
			//可以在本地记录每次收到的包的编号,
			//如果本地记录的包的编号与数据包发送回来的快编号不一致,则不做处理
			if(htons(num+1) == *(unsigned short*)(buf+2)){

				//将数据写入文件
				if(-1 == write(fd,buf+4,ret-4))
					ERR_MSG("write");

				buf[1] = 4;

				//发送ACK包
				if(-1 == sendto(cfd,buf,4,0,(struct sockaddr *)&sin,sizeof(sin)))
					ERR_MSG("sendto");

				if(ret-4<512){
					printf("文件%s下载完成\n\n",filename);
					break;
				}
				num++;
			}
		}
		else if(5 == buf[1]){
			printf("接收出错\n");
			return -1;
		}
	}
	close(fd);
	return 0;
}

//上传文件
int do_upload(int cfd,struct sockaddr_in sin){
	char buf[516] = "";
	ssize_t ret = 0;

	char filename[50] = "";
	printf("请输入要上传的文件名>>>");
	scanf("%s",filename);
	while(getchar()!=10);

	//判断文件是否存在
	int fd = open(filename,O_RDONLY);
	if(fd<0){
		ERR_MSG("open");
		return -1;
	}

	//创建数据包
	int size = sprintf(buf,"%c%c%s%c%s%c",0,2,filename,0,"octet",0);

	//发送请求
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MSG("sendto");
		return -1;
	}

	socklen_t addrlen = sizeof(sin);
	unsigned short num = 0;
	ssize_t ret_read = 0;

	while(1){
		//接收数据包
		ret = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);

		if(ret<0){

			ERR_MSG("recvfrom");
			return -1;
		}
		//检验ACK
		if(4 == buf[1]){

			//将文件读取出来
			//第一次返回的ACK的编号为0
			if(htons(num) == *(unsigned short*)(buf+2)){
				//组数据包
				num++;
				bzero(buf,sizeof(buf));
				*(short*)buf = htons(3);
				*(short*)(buf+2) = htons(num);

				ret_read = read(fd,buf+4,512);
				if(ret_read<0){
					ERR_MSG("read");
					break;
				}

				//上传数据包
				if(sendto(cfd,buf,ret_read+4,0,(struct sockaddr*)&sin,sizeof(sin))<0){

					ERR_MSG("sendto");
					break;
				}

				//当数据小于512时结束
				if(ret_read<512){
					printf("上传成功\n");
					return 0;
				}
			}
		}
	}

	//关闭文件
	close(fd);
}
int main(int argc, const char *argv[])
{

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

	//填充
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SER_PORT);
	sin.sin_addr.s_addr = inet_addr(SER_IP);

	char choose = 0;
	while(1){

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

		switch(choose){

		case '1':
			do_download(cfd,sin);
			break;
		case'2':
			do_upload(cfd,sin);
			break;
		case'3':
			goto END;
			break;
		default:
			printf("输入错误\n");
			break;
		}
		printf("输入任意字符清屏>>>");
		while(getchar()!=10);
	}


END:
	//关闭套接字
	close(cfd);


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值