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

发布时间:2026/7/20 21:09:40

【网络编程】TFTP简单文件传输协议、udp广播及多播 目录一、tftp概述二、TFTP的通信过程三、TFTP的协议报文分析四、抓包工具wireshark1、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通信过程总结无选项服务器在69号端口等待客户端的请求。服务器若批准此请求,则使用临时端口与客户端进行通信。每个数据包的编号都有变化从1开始。每个数据包都要得到ACK的确认如果出现超时,则需要重新发送最后的包数据或 ACK。数据的长度以512Byte传输 6、小于512Byte的数据意味着传输结束 。三、TFTP的协议报文分析六种报文ERROR(5)差错码信息差错码1File not found.2Access violation3Disk full or allocation exceeded4illegal TFTP operation5Unknown tlansfer ID6File already exists7No such user8Unsupported option(s) requestedTFTP带选项的读写报文通信过程tsize选项:当读操作时tsize选项的参数必须为“0”服务器会返回待读取的文件的大小当写操作时tsize选项参数应为待写入文件的大小服务器会回显该选项blksize选项:修改传输文件时使用的数据块的大小范围865464timeout选项:修改默认的数据传输超时时间单位秒四、抓包工具wireshark过滤规则1、IP过滤ip.src192.168.44.130只显示源IP为192.168.44.130的数据报文ip.dst192.168.44.130只显示目的IP为192.168.44.130的数据报文ip.addr192.168.44.130只显示示源IP或目的IP为192.168.44.130的数据报文2、协议过滤tcp udp arp tftp3、端口过滤udp.srcport8000只显示源端口为8000的udp报文udp.dstport8000只显示目的端口为8000的udp报文udp.port8000只显示目的或源端口为8000的udp报文tcp.srcport8000只显示源端口为8000的tcp报文tcp.dstport8000只显示目的端口为8000的tcp报文tcp.port8000只显示目的或源端口为8000的tcp报文4、mac地址过滤eth.srcaa:bb:cc:dd:ee:ff只显示源mac为aa:bb:cc:dd:ee:ff的数据报文eth.dstaa:bb:cc:dd:ee:ff只显示目的mac为aa:bb:cc:dd:ee:ff的数据报文 eth.addraa:bb:cc:dd:ee:ff只显示源mac或目的mac为aa:bb:cc:dd:ee:ff的数据报文5、逻辑与与逻辑或and 逻辑与 同时满足or || 逻辑或 只要有一个满足就行五、tftp示例编写TFTP客户端并不带选项 从服务器下载文件流程sockfd 创建UDP套接字构建读请求报文、并发送到服务器的69号端口fdopen以写的方式打开本地文件while(1){unsigned char buf[516];int len recvfrom(sockfd,buf,sizeof(buf),0, dst_addr,sizeof(ds_addr));write(fd,buf4,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网络时间协议NTP2、UDP广播的特点处于同一子网的所有主机都必须处理数据UDP数据包会沿协议栈向上一直到UDP层运行音视频等较高速率工作的应用会带来很大的负担局限于局域网内使用3、UDP广播地址定向广播地址主机ID全11、例对于192.168.44.0/24其定向广播地址为192.168.44.2552、通常路由器不转发该广播受限广播地址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; }

相关新闻