C中的非阻塞udp套接字编程:我得到了什么?

时间:2010-02-10 20:09:30

标签: sockets tcp udp blocking nonblocking

我在理解recv()/ recvfrom()从非阻塞UDP套接字返回时遇到了问题。

更具体一点,与TCP相比(如果我错了,请纠正我):

  • 阻塞套接字(TCP或UDP)不会从recv()返回,直到缓冲区中有一些数据。这可以是一些字节数(TCP)或完整的数据报(UDP)。

  • 非阻塞TCP套接字要么返回EWOULDBLOCK(linux)/ WSAEWOULDBLOCK(windows),要么返回当前缓冲区中的字节。由于TCP数据是流,因此返回的字节数无关紧要。

现在的问题是:

  • 如果没有可用数据,非阻塞UDP套接字也会返回WOULDBLOCK(linux)/ WSAEWOULDBLOCK(windows)。但是如果有数据可用,非阻塞UDP套接字只返回一些字节,这可能意味着你只得到一半的数据报或UDP套接字总是返回完整的数据报吗?

编辑:

我对“数据报的一半”的意思是:如果我在套接字当前正在接收数据报时调用recv()会发生什么。在那一刻,缓冲区中有一些字节,但数据报尚未完成。

您的解释和评论表示赞赏。谢谢!

3 个答案:

答案 0 :(得分:8)

最后,借口从我的旧办公室里挖出我的史蒂文斯书。

如果缓冲区足够大,标准的Berkeley套接字recv()recvfrom()函数将永远不会返回部分数据报。在内核完全接收并重新组装数据报之前,应用程序无法使用数据报。

有趣的是,今天的问题并不多(任何?),其他网络编程接口在提供的缓冲区太小时不同意行为:

  

传统的Berkeley版本的套接字API会截断数据报,丢弃任何多余的数据。是否通知应用程序取决于版本。 (4.3BSD Reno及以后可以通知应用程序数据报被截断。)

     

SVR4下的套接字API(包括Solaris 2.x)不会截断数据报。在后续读取中返回任何多余的数据。不通知应用程序从单个UDP数据报中实现多次读取。

     

TLI API不会丢弃数据。而是返回一个标志,指示有更多数据可用,并且应用程序的后续读取将返回数据报的其余部分。

(Stevens,TCP / IP Illustrated,第1卷,第160页)

答案 1 :(得分:1)

是的,UDP只返回在那个数据报中传输的数据。 UDP不像TCP那样面向流。数据报是离散传输,并不以任何方式与其他数据报联系在一起。这就是TCP的套接字选项是SOCK_STREAM的原因。

这方面的好处是你可以感受到单独的传输,这对TCP来说并不容易。

答案 2 :(得分:0)

我相信你只能获得一个或零个数据报。但是我现在不能支持这个。也许其他人可以提供一个很好的参考?

编辑:我很确定你不能收到半个数据报。数据报已经到达缓冲区,或者没有。