基于TCP的文件传输

1>fttf协议概述

简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输

特点:是应用层协议,基于UDP协议实现

数据传输模式:1、octet:二进制模式(常用)

2、mail:已经不再使用

cs 复制代码
#include<myhead.h>
#define SER_PORT 69      //服务器端口号
#define SER_IP "192.168.0.3"        //服务器ip地址

//客户端可绑定可不绑定
//#define CLI_POPR 5555              //客户端端口号
//#define CLI_IP "192.168.111.187"    //客户端ip地址

void menu()                    //菜单函数
{
	printf("******************\n");
	printf("******1.下载******\n");
	printf("******2.上传******\n");
	printf("******3.退出******\n");
	printf("******************\n");
}

//下载
int text_add()
{
	//创建套接字文件描述符
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-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);

	//下载数据
	char name[128]="";
	printf("请输入需要下载的文件名>>>");
	scanf("%s",name);

	//2向服务器下载请求
	char buf[516]="";
	short *p1=(short *)buf;  //操作码
	*p1=htons(1);

	char *p2=buf + 2;  //文件名  由自己输入
    strcpy(p2,name);   

	char *p4=p2+strlen(p2)+1;  //模式位   由用户输入
	strcpy(p4,"octet");
	int size=2+strlen(p2)+strlen(p4)+2;//请求包的总长度
	socklen_t addrlen=sizeof(sin);

	if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("sendto 1 error");
		return -1;
	}

	int fd=-1;     //文件描述符
	int res;    //字符数
	unsigned short num=1;
	while(1)
	{
		//清空容器
		bzero(buf,sizeof(buf));
		res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
		if(res==-1)
		{
			perror("recv error");
			return -1;
		}
		if(3==buf[1])
		{

			//判断块编号和本地块编号
			if(*(short *)(buf+2)==htons(num))
			{
				num++;
				fd=open(name,O_WRONLY|O_CREAT|O_TRUNC,0664);
				if(fd==-1)
				{
					perror("open error");
					return -1;
				}
			}
			//写数据
				write(fd,buf+4,res-4);
		
				//发送ack包
				buf[1]=4;
				if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1)
				{
					perror("sendto error");
					return -1;
				}

				if(res<516)
				{
					printf("下载成功\n");
					break;
				}
				
		}
		else if(buf[1]==5)
		{
			printf("error");
			break;

		}

	}

	//关闭套接字
	close(sfd);
	close(fd);
	return 0;
}

//上传
int up_text()
{
	//创建套接字文件描述符
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-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);

	//上传
	char name[128]="";
	printf("请输入需要上传的文件名>>>");
	scanf("%s",name);

	//打开文件  只读
	int rfd=-1;
	if((rfd=open(name,O_RDONLY))==-1)
	{
		perror("open error");
		return -1;
	}

	//2向服务器上传
	char buf[516]="";
	short *p1=(short *)buf;  //操作码
	*p1=htons(2);

	char *p2=buf + 2;  //文件名  由自己输入
	strcpy(p2,name);   

	char *p4=p2+strlen(p2)+1;  //模式位   由用户输入
	strcpy(p4,"octet");

	int size=2+strlen(p2)+strlen(p4)+2;//请求包的总长度
	socklen_t addrlen=sizeof(sin);

	if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("sendto error");
		return -1;
	}

	int res=0;    //字符数
	unsigned short num=0;
	while(1)
	{
		//清空容器
		bzero(buf,sizeof(buf));
		res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
		if(res==-1)
		{
			perror("recv error");
			return -1;
		}
		if(4==buf[1])
		{

			//判断块编号和本地块编号
			if(num==ntohs(*(short *)(buf+2)))
			{
				buf[1]=3;
				num++;
				*(short*)(buf+2)=htons(num);

				//读取数据
				res=read(rfd,buf+4,sizeof(buf)-4);
				if(res==0)
				{
					printf("上传成功\n");
					break;
				}
			}
			else
			{
				printf("上传失败\n");
				break;
			}
		}
		else if(5==buf[1])
		{
			perror("error");
			break;

		}
	}

	//关闭套接字
	close(sfd);
	close(rfd);
	return 0;
}



/************************主程序**************************/
int main(int argc, const char *argv[])
{

	int num=0;
	while(num!=3)
	{
		menu();       //调用菜单函数
		printf("请输入>>>");
		scanf("%d",&num);
		switch(num)
		{
		case 1:                    //下载

			text_add();          //调用下载函数
			break;

		case 2:                  //上传

			up_text();          //调用上传函数
			break;

		case 3:                  //退出

			break;

		default:
			printf("输入错误,请重新输入!\n");

		}

	}
	return 0;
}
相关推荐
热爱跑步的恒川3 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
云飞云共享云桌面4 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
音徽编程6 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零7 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
23zhgjx-NanKon8 小时前
华为eNSP:QinQ
网络·安全·华为
23zhgjx-NanKon8 小时前
华为eNSP:mux-vlan
网络·安全·华为
点点滴滴的记录8 小时前
RPC核心实现原理
网络·网络协议·rpc
Lionhacker9 小时前
网络工程师这个行业可以一直干到退休吗?
网络·数据库·网络安全·黑客·黑客技术
程思扬9 小时前
为什么Uptime+Kuma本地部署与远程使用是网站监控新选择?
linux·服务器·网络·经验分享·后端·网络协议·1024程序员节
ZachOn1y9 小时前
计算机网络:运输层 —— 运输层概述
网络·tcp/ip·计算机网络·运输层