2010-02-10 69 views
8

我在理解recv()/ recvfrom()从非阻塞UDP套接字返回时遇到问题。在C中的非阻塞udp套接字编程:我得到什么?

更具体一点,并与TCP(请纠正我,如果我错了):直到

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

  • 一个非阻塞的TCP套接字或者返回EWOULDBLOCK(linux)/ WSAEWOULDBLOCK(windows)或者当前在缓冲区中的字节。由于TCP数据是一个流,返回多少字节并不重要。

现在的问题:

  • 非阻塞UDP套接字也返回WOULDBLOCK(Linux)的/ WSAEWOULDBLOCK(窗口),如果没有可用数据。但是,如果有数据可用,那么非阻塞UDP套接字是否只返回一些字节,这可能意味着您只能获得数据报的一半或者UDP套接字始终返回完整的数据报?

编辑:

我指的是“一个数据包的一半”的是:会发生什么,如果我可以调用recv()在短短的时刻插座当前正在接收数据报。在那一刻,缓冲区中有一些字节,但数据报尚未完成。

您的解释和意见,赞赏。谢谢!

回答

8

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

如果缓冲区足够大,标准伯克利插座recv()recvfrom()函数将永远不会返回部分数据报。在内核完全接收并重组数据报之前,数据报不可用于应用程序。

有趣的是,这是没有太大的(任意?)问题的今天,其他网络编程接口不上行为一致时,所提供的缓冲区太小的:

传统的伯克利版本的套接字API截断数据报,丢弃任何多余的数据。应用程序是否被通知取决于版本。 (4。3BSD Reno及更高版本可以通知应用程序数据报已被截断。)

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

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

(史蒂文斯,TCP/IP详解,第1卷,第160页)

+0

它看起来像是可以在Linux中传递和接收MSG_TRUNC标志到'recvmsg'。在手册页recv(2)中记录。另一方面,也许我误读了,但是我只能找到'socket(2)'的manpage中记录的丢弃行为,它只为'SOCK_SEQPACKET'套接字提及。我从来没有亲自使用过这些。 – 2010-02-11 09:10:58

+0

'MSG_TRUNC'作为'recv(2)'的参数不是标准的。它在FreeBSD或Mac OS X上都不可用(我目前可以访问的系统,其他人可能也适用)。 'MSG_TRUNC'可以在'struct msghdr'的'flags'成员的Linux,FreeBSD和Mac OS X上传递给'recvmsg(2)'。在任何情况下,即使使用Linux上的'recv(2)',如果传递的缓冲区不够大,数据报将被截断。如果在那里使用MSG_TRUNC,调用者必须检查返回值并将其与缓冲区的大小进行比较。它会知道数据丢失,但仍然丢失。 – 2010-02-11 16:07:16

+0

谢谢!这意味着UDP是**真的**数据包导向... – Uwe 2010-02-11 17:34:43

0

我相信你只能得到一个或零个数据报。但这一刻我不能支持这一点。也许别人可以提供一个很好的参考?

编辑:我敢肯定,你不能接收一半的数据报。数据报已经到达缓冲区,或者没有。

+0

我相信这是正确的。如果它不适合您提供的缓冲区,或者如果您的mbufs不够大(有时会发生大量碎片数据报),您也可能会遇到错误。 – 2010-02-10 22:03:38

+0

mbufs是一个BSD内核数据结构。他们没有接触用户所在地。 – 2010-02-11 16:08:30

1

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

这样做的好处在于,您可以感受到单独的传输,这对于TCP来说并不容易。

+0

感谢你们俩。 我知道面向流的TCP(SOCK_STREAM)和面向数据包的UDP(SOCK_DGRAM)之间的区别。我只是不确定一个非阻塞的UDP recv()是否也是面向数据包的。引用recv()手册页: ...如果在套接字上没有可用的消息,则接收调用将等待消息到达,除非套接字是非阻塞的(请参阅fcntl(2)),在这种情况下返回值-1,并将外部变量errno设置为EAGAIN或EWOULDBLOCK。 **接收的电话通常会返回任何可用的数据,** ... – Uwe 2010-02-10 20:38:07