基于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;
}
相关推荐
JJJennie77710 小时前
MAI Gateway技术揭秘:大模型网关能做什么?从原理到落地
linux·服务器·网络·ai网关
Allen_LVyingbo10 小时前
医疗人工智能项目全生命周期管理系统:监管知识建模、工程实现与实证评估(上)
网络·人工智能·机器学习·语言模型·自动化
新时代牛马16 小时前
嵌入式网络完整篇:从LwIP/以太网驱动到 Linux netdev 与排障
linux·网络·php
发光小北16 小时前
西门子 PLC 串口转网口模块现场应用有哪些问题?
网络协议
上海云盾-小余17 小时前
BGP 高防底层原理:TCP 异常流量识别与清洗机制
运维·网络·tcp/ip
captain37617 小时前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee
同元软控17 小时前
从排队、碰撞到信号波形:基于Sysevents的网络—信号一体化仿真
网络
言乐618 小时前
Python加速器4跨境网络加速器
运维·服务器·开发语言·网络·python
疯狂打码的少年19 小时前
【计算机网络】IPv6基础(特点、表示法、与IPv4对比)
网络·笔记·计算机网络
楚Y6同学19 小时前
QT上位机开发-UDP通信-模拟下位机数据联调的方法
网络协议·udp·联调方法