如何接收长度小于18+20+8的UDP组播数据包?
接收小于46字节的UDP组播数据包解决方案
首先明确:你提到的18(以太网头部)+20(最小IP头部)+8(UDP头部)=46字节,是以太网链路层的最小净荷长度。如果UDP数据包(IP+UDP+数据)总长度小于46字节,以太网会自动填充到46字节,但IP和UDP头部的长度字段会准确记录实际的数据包长度,接收端可通过解析这些字段拿到真实的小数据包。
针对你使用的mcreceive工具,可通过以下步骤处理:
解析IP与UDP头部的长度字段
收到数据包后,不要直接把整个接收缓冲区内容当成有效数据,而是:- 从IP头部(接收数据的前20字节起)提取
总长度字段(IP头部第3、4字节,网络字节序需转为主机字节序),该值是IP数据包的实际总长度(IP头部+UDP头部+数据)。 - 提取IP头部的
头部长度字段(IP头部第1字节的后4位,乘以4得到实际IP头部字节数)。 - 计算UDP数据长度:用IP总长度减去IP头部长度,再减去8字节UDP头部,得到真实数据长度。
- 从IP头部(接收数据的前20字节起)提取
修改mcreceive代码实现
原mcreceive核心是调用recvfrom读取数据,可在接收后添加解析逻辑:// 假设buf为接收缓冲区,len为recvfrom返回的长度 struct iphdr *ip = (struct iphdr *)buf; int ip_header_len = ip->ihl * 4; // 计算IP头部实际字节数 int ip_total_len = ntohs(ip->tot_len); // 转为主机字节序的IP总长度 struct udphdr *udp = (struct udphdr *)(buf + ip_header_len); int actual_data_len = ntohs(udp->len) - 8; // 减去UDP头部8字节,得到真实数据长度 // 从buf + ip_header_len + 8位置读取actual_data_len长度的内容,即为实际小数据包这样就能过滤以太网填充的无效字节,获取真实的小数据包。
检查socket选项配置
确保未设置会篡改数据包长度的socket选项,比如SO_RCVBUF过小可能导致截断,默认配置下只要缓冲区足够,就能完整接收包含IP头部的数据包,后续解析即可。
内容的提问来源于stack exchange,提问作者q0987
相关产品推荐
相关产品推荐

