我可以从套接字中读取一个UDP数据包吗?
在Linux上使用UNIX套接字API,有什么方法可以保证我读取一个UDP数据包,并且只有一个UDP数据包?我正在使用recvmsg从非阻塞套接字读取数据包,其缓冲区大小比内部网络的MTU稍大。这应该确保我总是可以收到完整的UDP数据包,但是我不确定如果数据包很小,我不能保证每次recvmsg呼叫都不会收到多个数据包。我可以从套接字中读取一个UDP数据包吗?
recvmsg手册页引用MSG_WAITALL选项,该选项尝试等待,直到填充缓冲区。我们没有使用这个,那么这意味着recvmsg将在读取一个数据报后总是返回?有什么方法可以保证这一点?
理想情况下,我想要一个跨UNIX解决方案,但如果不存在,那么Linux是否有特定的解决方案?
recvmsg
会返回给你一个数据包,它将是整个数据包(只要你提供的缓冲区足够大)。
的recvmsg()函数将接收来自连接模式或连接模式的插座的消息。
“消息”是指恰好一个消息(或数据包),并且,
对于基于消息的插座,如SOCK_DGRAM和SOCK_SEQPACKET,整个消息必须在单个操作中被读取。
如果有碎片。只有在整个数据包重建后,'''recievemsg'''才会返回数据? – Artium 2016-12-27 20:48:40
Artium:是的,这是由操作系统执行的,用户空间只会看到组合的数据包而不是碎片。这意味着接收到的碎片数据包将被操作系统保留一段时间,等待其余的碎片。 – 2017-01-05 12:48:42
一个选项(我说选项)是使用使用libpcap的pcap_next并拆开它来看它是否是udp数据包。你可以这样做:
/* jump pass the ethernet header */
ipdata = (struct ip*)(packet + sizeof(struct ether_header));
length -= sizeof(struct ether_header);
(从tcpdump的借用)
,然后测试的IP结构,看它是否是一个UDP数据包做:
if (ipdata->ip_p == IPPROTO_UDP)
如果失败,保持循环(调用pcap_next),直到你得到你的udp包。当然,这种方法提取udp数据报更加困难,但它确实可以让你很好地进入数据包内部。请参阅tcpdump源文件以了解如何去除信息并发布。
MSG_WAITALL面向流的套接字:http://linux.die.net/man/3/recvmsg正如已经回答的那样,recv/send()使用整个数据报工作,用于面向数据报的套接字。 – Ioan 2010-03-30 19:57:44