【无标题】网络编程作业4

本文介绍了使用C语言实现的基于用户数据报协议(UDP)的TrivialFileTransferProtocol(TFTP)文件传输功能,包括下载和上传过程中的数据包处理及错误处理。程序提供了一个简单的文件管理器界面供用户选择上传或下载操作。
摘要由CSDN通过智能技术生成

1、基于UDP的TFTP文件传输

#include <allhead.h>


int download(int cfd,struct sockaddr_in sin)
{
	char buf[516]=""; //定义资源包
	char filename[128]="";
	printf("请输入文件名:");
	scanf("%s",filename);
	while(getchar()!=10);

	//打开文件
	int fd = -1;
	printf("%s\n",filename);
	if((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1)
	{
		perror("open");
		return -1;
	}
	//组装请求包
	short* p1 = (short*)buf;
	*p1 = htons(1);
	char* p2 = buf+2;
	strcpy(p2,filename);
	char* p3 = p2+strlen(p2)+1;
	strcpy(p3,"octet");
	int size = 4+strlen(p2)+strlen(p3);
	//发送下载请求包到服务器
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1)
	{
		perror("sendto");
		return -1;
	}
	printf("请求成功\n");
	socklen_t socklen = sizeof(sin);

	char* p5 = buf+4;

	while(1)
	{
		memset(buf,0,sizeof(buf));
		int res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
		short a = ntohs(*(short*)buf);
		short b = ntohs(*(short*)(buf+2));
		
	//printf("%d\n %d\n",a,b);
		if(a == 3)    //表明是数据包
		{
			write(fd,p5,res-4);
			*p1=htons(4);  //修改操作码来代替ACK返回
			sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));
		}else if(a==5)
		{
			printf("%s\n",p5);
			return -1;
		}
		if(res<516){break;} //当接收到的字节数小于516说明已经接收完成,跳出循环
	}
	printf("下载完成!\n");
	close(fd);

}

int upload(int cfd,struct sockaddr_in sin)
{
	char buf[516]=""; //定义资源包
	char filename[128]="";
	printf("请输入文件名:");
	scanf("%s",filename);
	while(getchar()!=10);

	//打开文件
	int fd = -1;
	if((fd = open(filename,O_RDONLY)) == -1)
	{
		perror("open");
		return -1;
	}
	//组装请求包
	short* p1 = (short*)buf;
	*p1 = htons(2);
	char* p2 = buf+2;
	strcpy(p2,filename);
	char* p3 = p2+strlen(p2)+1;
	strcpy(p3,"octet");
	int size = 4+strlen(p2)+strlen(p3);

	//发送上传请求包到服务器
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1)
	{
		perror("sendto");
		return -1;
	}
	printf("请求成功\n");
	socklen_t socklen = sizeof(sin);

	int n=0;
	while(1)
	{
		memset(buf,0,sizeof(buf));
		recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&socklen);
		int res = read(fd,buf+4,512);//将文件读入buf的数据域中
		//printf("%d\n",res);
		*p1=htons(3); //修改操作码为3 作为数据包进行传输
        n++;
		*(short*)(buf+2)=htons(n);
		//printf("%d\n",n);

		//发送buf到服务器
		sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
		if(res == 0){break;}//当read返回值为0时表示数据已经读取完毕
	}
	printf("上传完成!\n");
	close(fd);

}
int main(int argc, const char *argv[])
{	
	if(argc != 2)
	{
		printf("请输入IP地址\n");
		return -1;
	}

	//1、创建用于通信的套接字文件描述符
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1)
	{
		perror("socket");
		return -1;
	}


	//3、消息收发
	//3.1定义一个地址信息结构体接收客户端地址信息
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(69);
	sin.sin_addr.s_addr = inet_addr(argv[1]);

	//界面设计
	printf("\033[01;33;10m>>>>>>>文件管理器<<<<<<<\n");
	printf("\033[01;34;10m>>>>>>>1.上传<<<<<<<\n");
	printf(">>>>>>>2.下载<<<<<<<\n");
	printf(">>>>>>>3.退出<<<<<<<\n");

	int Down,Up;
	while(1)
	{
		printf("\033[01;32;10m请选择:\033[0m");
		int sel;
		scanf("%d",&sel);
		switch(sel)
		{
		case 2:   //下载
			Down = download(cfd,sin);
			break;

		case 1:   //上传
			Up = upload(cfd,sin);
			break;

		case 3:
			return 0;

		default:
			printf("请输入正确选项!\n");
		}

	}
	close(cfd);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值