非阻塞 UDP 写入返回的字节数是不是少于请求的字节数?

Posted

技术标签:

【中文标题】非阻塞 UDP 写入返回的字节数是不是少于请求的字节数?【英文标题】:Can a Non Blocking UDP write return with fewer bytes than requested?非阻塞 UDP 写入返回的字节数是否少于请求的字节数? 【发布时间】:2012-05-05 18:36:00 【问题描述】:

我有一个应用程序,它通过可以在单工(单向传输)或双工模式(双向)下运行的链路从发送方到接收方点对点发送数据。在单工模式下,应用程序使用 UDP 发送数据,而在双工模式下,它使用 TCP。由于 TCP 套接字上的写入可能会阻塞,因此我们使用非阻塞 IO(带有 FIONBIO 的 ioctl - 此发行版不支持 O_NONBLOCK 和 fcntl)和 select() 系统调用来确定何时可以写入数据。使用 NIO 是为了在网络状况恶化时,如果需要,我们可以在超时后提前中止发送。我想使用相同的基本代码进行发送,而是在更高抽象的 TCP/UDP 之间进行更改。这对 TCP 非常有用。

但是我担心非阻塞 IO 如何用于 UDP 套接字。我可能错误地阅读了手册页,但由于 write() 可能返回指示发送的字节数少于请求的字节数,这是否意味着客户端将在其数据报中收到更少的字节数?要发送给定的数据缓冲区,可能需要多次写入,这可能是因为我使用的是非阻塞 IO。我担心这会转化为客户端收到的多个 UDP 数据报。

我对套接字编程相当陌生,所以如果在这里有一些误解,请原谅我。谢谢。

【问题讨论】:

您可能想检查您正在使用的任何系统的详细信息;您的 UDP 堆栈可能有特定的限制(确实如此,正如您已经说过的那样)。 【参考方案1】:

假设一个正确(未损坏)的 UDP 实现,那么每个 send/sendmsg/sendto 将对应于一个完整的数据报发送,每个 recv/recvmsg/recvfrom 将对应于一个完整的数据报接收。

如果 UDP 消息无法完整传输,您应该会收到 EMSGSIZE 错误。由于网络中某个点的大小,发送的消息可能仍然失败,在这种情况下,它根本不会到达。但它不会分段交付(除非 IP 堆栈存在严重错误)。

一个好的经验法则是将您的 UDP 有效负载大小保持在最多 1400 字节。这是非常近似的,并且为各种形式的隧道留出了很大的空间,以避免碎片化。

【讨论】:

谢谢。我进行了更多测试,发现我的整个有效负载或没有任何有效负载是针对使用 UDP 的给定 write() 调用发送的——这确实是发生的唯一合乎逻辑的事情。我在 VxWorks 5.5 上使用供应商提供的堆栈来支持 TOE……我对在目标平台上看不到 EMSGSIZE 并不感到惊讶。无论如何,感谢您的权威回应,这绝对有助于提供我已经涵盖了基础的信心。

以上是关于非阻塞 UDP 写入返回的字节数是不是少于请求的字节数?的主要内容,如果未能解决你的问题,请参考以下文章

阻塞 recv() 返回小于请求字节的情况

对于 UDP 套接字,发送函数不会失败,但写入的数据仍然比请求的少吗?

read/write函数与(非)阻塞I/O的概念

阻塞式I/0 和 非阻塞式I/O 同步异步详细介绍

非阻塞方式socket send()返回大小和实际发送大小不一致

概念理解同步异步阻塞非阻塞