项目:基于UDP的TFTP文件传输

news/2024/5/18 15:13:41 标签: udp, 单片机, 网络协议

1)tftp协议概述

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

特点:
是应用层协议
基于UDP协议实现
数据传输模式
octet:二进制模式(常用)
mail:已经不再支持
在这里插入图片描述
在这里插入图片描述

TFTP通信过程总结

服务器在69号端口等待客户端的请求
服务器若批准此请求,则使用 临时端口 与客户端进行通信。
每个数据包的编号都有变化(从1开始)
每个数据包都要得到ACK的确认,如果出现超时,则需要重新发送最后的数据包或ACK包
数据长度以512Byte传输的,小于512Byte的数据意味着数据传输结束。

3)tftp协议分析

在这里插入图片描述
代码:

#include <head.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet.h>

#define PORT 69
#define IP "10.102.145.165"
int main(int argc, const char *argv[])
{
	//创建报式套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd < 0)
	{
		ERRO_MES("socket");
		return -1;
	}
	printf("cfd = %d\n",cfd);

	//填充服务器的地址信息结构体,给sendto函数使用
	//发送给谁,就填谁的地址信息
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET; //必须填AF_INET
	sin.sin_port  		= htons(PORT); //端口号:服务器绑定的端口号
	sin.sin_addr.s_addr = inet_addr(IP); //IP:服务器绑定的IP

	char choose = 0;
	while(1)
	{
		printf("*********************\n");
		printf("********1. 下载******\n");
		printf("********2. 上传******\n");
		printf("********3. 退出******\n");
		printf("*********************\n");
		printf("请输入>>> ");

		choose = getchar();
		while(getchar() != 10); //循环获取字符串直到遇到/n结束循环

		switch(choose)
		{
		case '1':do_download(cfd,sin);break;
		case '2':do_upload;break;
		case '3':goto END;break;
		default:printf("输入错误,请重新输入\n");
		}
	}
END:
	//关闭文件描述符
	close(cfd);
	return 0;
}
int do_download(int cfd,struct sockaddr sin)
{
	//发送下载请求
	char buf[516] = "";
	char name[20] = "";
	printf("请输入要下载的文件名>>> ");
	scanf("%s",name);
	while(getchar()!=10);

	unsigned short *p1 = (unsigned short*)buf;
	*p1 = htons(1);

	char* p2 =buf+2;
	strcpy(p2, name);

	char *p = p2+strlen(p2);
	*p3 = 0;

	char* p4 = p3+1;
	strcpy(p4,"octet");

	int size = 2+strlen(p2)+1+strlen(p4)+1;
	if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		ERRO_MES("sendto");
		return -1;
	}

	//打开文件,用于存储下载后的文件
	int fd = -1;  //必须初始化成一个无效的文件描述符
	socklen_t addrlen = sizeof(sin);
	ssize_t res = 0;
	unsigned short num = 0; //记录本地的块编号

	while(1)
	{
		bzero(buf,sizeof(buf));
		//接收数据
		res = recvfrom(cfd,buf,sizeof(buf).0,(struct sockaddr*)&sin,&addrlen);
		if(res < 0)
		{
			ERRO_MES("recvfrom");
			return -1;
		}
		//由于操作码占两个字节,且是大端字节序
		//所以低字节存储在高地址,高字节存储在低地址
		//有效操作码,存储在高地址上,即buf[1]的位置
		if(3 == buf[1])
		{
			//判断服务器返回的数据包的块编号与本地记录的块编号是否一致
			if(*(unsigned short*)(buf+2) == htons(num+1))
			{
				num++; //更新本地记录的块编号

				if(-1 == fd)
				{
					fd = open(name,O_WRONLY | O_CREAT | O_TRUNC,0664);
					if(fd < 0)
					{
						ERRO_MES("open");
						return -1;
					}
				}

				//将数据写入到文件中
				if(write(fd,buf+4,res-4) < 0)
				{
					ERRO_MES("write");
					close(fd);
					return -1;
				}

				//发送ACK,发送到临时端口
				buf[1] = 4;
				if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
				{
					ERRO_MES("sendto");
					return -1;
				}

				//若接收到的数据小于512跳出循环,结束下载
				if(res-4 < 512)
				{
					printf("%s 文件下载完毕\n",name);
					break;
				}
			}
		}
		else if(5 == buf[1]) //错误包
		{
			printf("错误:%d %s\n",ntohs(*(short*)(buf+2)),buf+4);
			close(fd);
			return -1;
		}
	}
	close(fd);
	return 0;
}


http://www.niftyadmin.cn/n/4940552.html

相关文章

使用 NLP 进行文本摘要

一、说明 文本摘要是为较长的文本文档生成简短、流畅且最重要的是准确摘要的过程。自动文本摘要背后的主要思想是能够从整个集合中找到最重要信息的一小部分&#xff0c;并以人类可读的格式呈现。随着在线文本数据的增长&#xff0c;自动文本摘要方法可能会非常有用&#xff0c…

Spring项目整合过滤链模式~实战应用

代码下载 设计模式代码全部在gitee上,下载链接: https://gitee.com/xiaozheng2019/desgin_mode.git 日常写代码遇到的囧 1.新建一个类,不知道该放哪个包下 2.方法名称叫A,干得却是A+B+C几件事情,随时隐藏着惊喜 3.想复用一个方法,但是里面嵌套了多余的逻辑,只能自己拆出来…

org/gradle/internal/service/DefaultServiceRegistry

编译 thingsboard 时报错 Caused by: org.apache.maven.plugin.PluginContainerException: A required class was missing while executing org.thingsboard:gradle-maven-plugin:1.0.11:invoke: org/gradle/internal/service/DefaultServiceRegistry 原因分析及解决办法如下…

深入探索Spring框架:解密核心原理、IOC和AOP的奥秘

深入探索Spring框架&#xff1a;解密核心原理、IOC和AOP的奥秘 1. 理解 Spring 的核心原理1.1 控制反转&#xff08;IOC&#xff09;1.2 面向切面编程&#xff08;AOP&#xff09; 2. 深入 IOC 容器的实现机制2.1 容器的创建2.2 Bean 的生命周期2.3 依赖注入 3. 深入 AOP 的实现…

字节跳动在PGO反馈优化技术上的探索与实践

背景 随着字节跳动的业务迅速增长&#xff0c;微服务的性能优化工作显得尤为重要&#xff0c;对于头部应用来说&#xff0c;提升若干百分点的性能也能为公司节省巨大的服务器资源成本。 编译器优化是软件性能优化的一种常用方法&#xff0c;相比其它特定的性能优化方法&#…

【Linux命令详解 | ps命令】 ps命令用于显示当前系统中运行的进程列表,帮助监控系统状态。

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 基本用法2. 显示所有进程3. 显示进程详细信息4. 根据CPU使用率排序5. 查找特定进程6. 显示特定用户的进程7. 显示进程内存占用8. 查看进程树9. 实时监控进程10. 查看特定进程的详细信息11. 查看特定用户的进程统计…

【产品人卫朋】硬件产品经理:产品成功的四个要素

目录 要素一&#xff1a;快速行动 要素二&#xff1a;衡量产品增长力 了解你的目标用户 衡量用户参与度 要素三&#xff1a;避免浪费金钱 要素四&#xff1a;组建一支能打的团队 硬件产品的成功离不开四个核心要素&#xff0c;分别是&#xff1a; &#xff08;1&#xf…

jmeter返回值中的中文显示为????问号处理解决方案

jmeter返回值中的中文显示为????问号 查找解决方案时&#xff0c;发现了以下两种解决方案&#xff1a; 一、1.打开jmter配置文件bin/jmeter.properties 2.修改配置文件&#xff0c;查找“sampleresult.default.encoding”将其改为utf8&#xff0c;注意要去掉“#”号 sample…