news 2026/7/20 21:09:23

【网络编程】TFTP简单文件传输协议、udp广播及多播

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【网络编程】TFTP简单文件传输协议、udp广播及多播

目录

一、tftp概述

二、TFTP的通信过程

三、TFTP的协议报文分析

四、抓包工具wireshark

1、IP过滤

2、协议过滤

3、端口过滤

4、mac地址过滤

5、逻辑与与逻辑或

五、tftp示例

六、UDP广播

1、广播的概述

2、UDP广播的特点

3、UDP广播地址

4、广播与单播的对比

​编辑 5、广播编程

6、udp多播(组播)

1、多播的概述

2、多播地址

3、多播地址结构体


一、tftp概述

tftp:简单文件传输协议、基于UDP协议。

数据传输模式:

octet:二进制模式 netascii:文本模式

二、TFTP的通信过程

TFTP通信过程总结(无选项)

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

三、TFTP的协议报文分析

六种报文:

ERROR(5)差错码信息
差错码
1File not found.
2Access violation
3Disk full or allocation exceeded
4illegal TFTP operation
5Unknown tlansfer ID
6File already exists
7No such user
8Unsupported option(s) requested

TFTP带选项的读写报文:

通信过程:

tsize选项:

操作时,tsize选项的参数必须为“0”,服务器会返回待读取的文件的大小
操作时,tsize选项参数应为待写入文件的大小,服务器会回显该选项

blksize选项:

修改传输文件时使用的数据块的大小(范围:8~65464)

timeout选项:

修改默认的数据传输超时时间(单位:秒)

四、抓包工具wireshark

过滤规则:

1、IP过滤

ip.src==192.168.44.130只显示源IP为192.168.44.130的数据报文

ip.dst==192.168.44.130只显示目的IP为192.168.44.130的数据报文

ip.addr==192.168.44.130只显示示源IP或目的IP为192.168.44.130的数据报文

2、协议过滤

tcp udp arp tftp

3、端口过滤

udp.srcport==8000只显示源端口为8000的udp报文

udp.dstport==8000只显示目的端口为8000的udp报文

udp.port==8000只显示目的或源端口为8000的udp报文

tcp.srcport==8000只显示源端口为8000的tcp报文

tcp.dstport==8000只显示目的端口为8000的tcp报文

tcp.port==8000只显示目的或源端口为8000的tcp报文

4、mac地址过滤

eth.src==aa:bb:cc:dd:ee:ff只显示源mac为aa:bb:cc:dd:ee:ff的数据报文

eth.dst==aa:bb:cc:dd:ee:ff只显示目的mac为aa:bb:cc:dd:ee:ff的数据报文 eth.addr==aa:bb:cc:dd:ee:ff只显示源mac或目的mac为aa:bb:cc:dd:ee:ff的数据报文

5、逻辑与与逻辑或

and ==> && 逻辑与 同时满足

or ==> || 逻辑或 只要有一个满足就行

五、tftp示例

编写TFTP客户端(并不带选项) 从服务器下载文件

流程:

sockfd = 创建UDP套接字

构建读请求报文、并发送到服务器的69号端口

fd=open以写的方式打开本地文件

while(1)

{

unsigned char buf[516]="";

int len = recvfrom(sockfd,buf,sizeof(buf),0, &dst_addr,sizeof(ds_addr));

write(fd,buf+4,len‐4);

if(len < 516)

break;

}

close(fd);

close(sockfd);

构建下载a.txt的报文:

unsigned char read_cmd[128]="";

int s_len = sprintf(read_cmd,"%c%c%s%c%s%c",0,1,"a.txt", 0,"octet", 0);

sendto(sockfd,read_cmd,s_len,0,dst_addr‐‐>69 )

tftp客户端(下载文件):

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> static int sockfd; void sig_dispose(int sig) { if (SIGINT == sig) { close(sockfd); puts("\nclose!"); exit(0); } } /*********************************************************************** * 函数名称: int main(int argc, char *argv[]) 函数功能: tftp客户端程序,可以从tftp服务器下载程序 ************************************************************************/ int main(int argc, char *argv[]) { unsigned short p_num = 0; unsigned char cmd = 0; char cmd_buf[512] = ""; char recv_buf[516] = ""; struct sockaddr_in client_addr; socklen_t cliaddr_len = sizeof(client_addr); signal(SIGINT, sig_dispose); if (argc < 3) { // 如果参数个数小于3,则认为输入命令错误 printf("cmd example:./tftpc 192.168.8.8 hello.txt\n"); return 0; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket error"); exit(-1); } struct sockaddr_in dest_addr; bzero(&dest_addr, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(69); inet_pton(AF_INET, argv[1], &dest_addr.sin_addr.s_addr); // 构造下载请求,argv[2]为文件名 int len = sprintf(cmd_buf, "%c%c%s%c%s%c", 0, 1, argv[2], 0, "octet", 0); sendto(sockfd, cmd_buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); int fd = open(argv[2], O_WRONLY | O_CREAT, 0666); if (fd < 0) { perror("open error"); close(sockfd); exit(-1); } do { // 接收服务器发送的内容 len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&client_addr, &cliaddr_len); cmd = recv_buf[1]; if (cmd == 3) // 是否为数据包 { // 接收的包编号是否为上次包编号+1 if ((unsigned short)(p_num + 1) == ntohs(*(unsigned short *)(recv_buf + 2))) { write(fd, recv_buf + 4, len - 4); p_num = ntohs(*(unsigned short *)(recv_buf + 2)); printf("recv:%d\n", p_num); // 十进制方式打印包编号 } recv_buf[1] = 4; sendto(sockfd, recv_buf, 4, 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); } else if (cmd == 5) // 是否为错误应答 { close(sockfd); close(fd); unlink(argv[2]); // 删除文件 printf("error:%s\n", recv_buf + 4); exit(-1); } } while (len == 516); // 如果收到的数据小于516则认为出错 close(fd); return 0; }

六、UDP广播

1、广播的概述

广播:由一台主机向该主机所在子网内的所有主机发送数据的方式

广播只能用UDP或原始IP实现不能用TCP

以下几个协议都用到广播

  • 地址解析协议(ARP)
  • 动态主机配置协议(DHCP)
  • 网络时间协议(NTP)

2、UDP广播的特点

  • 处于同一子网的所有主机都必须处理数据
  • UDP数据包会沿协议栈向上一直到UDP层
  • 运行音视频等较高速率工作的应用,会带来很大的负担
  • 局限于局域网内使用

3、UDP广播地址

定向广播地址:主机ID全1

1、例:对于192.168.44.0/24,其定向广播地址为192.168.44.255

2、通常路由器不转发该广播

受限广播地址:255.255.255.255

路由器从不转发该广播

4、广播与单播的对比

单播:

广播:

5、广播编程

socket函数创建的套接字 一般不支持广播。

setsockopt函数 可以让 套接字 支持广播。

int setsockopt(int sockfd, int level,int optname,const void *optval, socklen_t optlen);

参数说明:

成功执行返回0,否则返回-1

示例:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char const *argv[]) { // 创建一个udp套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 使用setsockopt函数设置sockfd支持广播 int yes = 1; setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int)); // 发送广播数据 struct sockaddr_in dst_addr; bzero(&dst_addr, sizeof(dst_addr)); // memset(&dst_addr,0,sizeof(dst_addr)); dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(8000); inet_pton(AF_INET, "192.168.131.255", &dst_addr.sin_addr.s_addr); sendto(sockfd, "broadcast msg", strlen("broadcast msg"), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)); close(sockfd); return 0; }

6、udp多播(组播)

1、多播的概述

多播:数据的收发仅仅在同一分组中进行

多播的特点:

  • 多播地址标示一组接口
  • 多播可以用于广域网使用
  • 在IPv4中,多播是可选的

2、多播地址

多播IP地址范围:224.0.0.1 ~ 239.255.255.254

多播mac地址映射: 前5位固定,后23位映射

通信过程:

基于mac地址的不完备硬件过滤+基于IP地址的完备软件过滤

3、多播地址结构体

setsockopt函数支持多播:

int setsockopt(int sockfd, int level,int optname, const void *optval, socklen_t optlen);

参数说明:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char const *argv[]) { // 创建一个udp套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // bind绑定固定端口 struct sockaddr_in my_addr; bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(8000); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)); // 使用setsockopt函数加入224.0.0.2多播组中 struct ip_mreq mreq; // inet_pton(AF_INET,"224.0.0.2",&mreq.imr_multiaddr.s_addr); mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.3"); // 多播组IP mreq.imr_interface.s_addr = inet_addr("192.168.44.131"); // 加入多播组的IP setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)); // 接收多播组的消息 while (1) { unsigned char buf[1500] = ""; recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); printf("%s\n", buf); } close(sockfd); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 21:07:04

AI应用开发技术栈选型:RAG、微调与提示词工程实战

1. AI应用开发的技术栈选择困境 刚入行AI应用开发时&#xff0c;我花了整整三个月在PyTorch源码里打转。直到完成第一个商业项目后才明白&#xff1a;大多数应用场景根本不需要从矩阵乘法开始写起。这个认知转变让我重新审视了AI开发的技术栈选择问题。 当前AI应用开发主要存在…

作者头像 李华
网站建设 2026/7/20 21:04:35

Hyperf框架入门:高性能PHP协程开发指南

1. Hyperf框架概述&#xff1a;高性能PHP协程框架 Hyperf是一个基于Swoole/Swow协程的高性能PHP框架&#xff0c;专为构建微服务和中台系统而设计。我第一次接触这个框架是在2019年&#xff0c;当时正在寻找能够替代传统PHP-FPM架构的解决方案。经过三年多的实际项目验证&…

作者头像 李华
网站建设 2026/7/20 21:02:18

深入解析PDMA的AASRC模式:多路数据流高效搬运实战指南

1. 项目概述&#xff1a;为什么需要深入理解PDMA的AASRC模式&#xff1f;在嵌入式系统开发&#xff0c;尤其是涉及音频、视频或高速传感器数据处理的领域&#xff0c;工程师们常常面临一个核心挑战&#xff1a;如何在不占用CPU大量资源的前提下&#xff0c;高效、可靠地搬运海量…

作者头像 李华
网站建设 2026/7/20 21:01:12

Ubuntu rootfs构建指南:从基础到定制化系统

1. 项目概述构建自定义的Ubuntu rootfs&#xff08;根文件系统&#xff09;是嵌入式开发和系统定制中的常见需求。与传统的BusyBox、Yocto或Buildroot方案相比&#xff0c;基于ubuntu-base的方案具有以下优势&#xff1a;完整的APT包管理体系丰富的软件源支持成熟的社区生态跨架…

作者头像 李华
网站建设 2026/7/20 20:59:46

linux基于wifi,Xshell的远程连接

最近有个比赛&#xff0c;要使用ros小车但是系统是ubuntu20.04无桌面系统刚开始接触linux的我啥都不会&#xff0c;就一个简单的连接wifi都搞了3天才搞通。再此进行一个总结。参考博客原文链接&#xff1a;https://blog.csdn.net/qq_51491920/article/details/126221940 一、什…

作者头像 李华
网站建设 2026/7/20 20:54:38

ng-animate与Angular路由动画集成:打造流畅的页面过渡效果

ng-animate与Angular路由动画集成&#xff1a;打造流畅的页面过渡效果 【免费下载链接】ng-animate &#x1f319; A collection of cool, reusable and flexible animations for Angular 14 项目地址: https://gitcode.com/gh_mirrors/ng/ng-animate 在现代Web应用开发…

作者头像 李华