基于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;
}
相关推荐
ATCH IERV7 分钟前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
锅挤38 分钟前
计算机网络复习(第五章):传输层
网络·计算机网络
mounter6251 小时前
深入理解 Linux 网络新特性:netkit 中的 RX/TX Queue Leasing 与 TCP Devmem
linux·服务器·网络·tcp/ip·kernel
空中海1 小时前
02. 静态逆向、Manifest 分析与 Smali 重打包
服务器·网络·windows
时空自由民.1 小时前
CAN ,CANFD,EtherCAT介绍
网络协议·计算机网络
计算机安禾1 小时前
【计算机网络】第3篇:网络编程范式的演进——阻塞IO、非阻塞IO与IO多路复用的比较研究
网络·计算机网络
炘爚1 小时前
TCP三次握手和四次挥手
服务器·网络·tcp/ip
你的保护色1 小时前
光纤到户常用架构介绍(无源光网络PON,有源光网络AON)
网络·架构
Gh0st_Lx2 小时前
【6】为什么有了 HTTP/1.1 ,还要 HTTP/2 和 HTTP/3
网络协议·http·php
学编程就要猛2 小时前
JavaEE初阶:网络原理-HTTP(下)
网络·网络协议·http