用 C 语言进行非阻塞 udp 套接字编程:我能得到什么?
我在理解从非阻塞 UDP 套接字返回什么recv()/recvfrom() 时遇到问题。
与 TCP 相比,更具体一点(如果我错了,请纠正我):
阻塞套接字(TCP 或 UDP)不会从 recv() 返回,直到缓冲区中有一些数据。这可能是一些字节数 (TCP) 或完整的数据报 (UDP)。
非阻塞 TCP 套接字要么返回 EWOULDBLOCK (linux) / WSAEWOULDBLOCK (windows),要么返回缓冲区中当前的字节。由于 TCP 数据是流,因此返回多少字节并不重要。
现在的问题是:
- 如果没有可用数据,非阻塞 UDP 套接字也会返回 WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows)。但是,如果有可用数据,非阻塞 UDP 套接字是否只返回一些字节,这可能意味着您只能获得一半的数据报,或者 UDP 套接字总是返回完整的数据报?
编辑:
我所说的“数据报的一半”的意思是:如果我在套接字当前正在接收数据报的那一刻调用recv(),会发生什么。此时缓冲区中有一些字节,但数据报尚未完成。
感谢您的解释和评论。谢谢!
I have a problem in understanding what recv()/recvfrom() return from an non-blockig UDP socket.
A bit more specific and compared to TCP (please correct me if I'm wrong):
A blocking socket (either TCP or UDP) won't return from a recv() until there is some data in the buffer. This could be some number of bytes (TCP) or a complete datagram (UDP).
A non-blocking TCP socket either returns EWOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) or the bytes that are currently in the buffer. As TCP data is a stream it doesn't matter how many bytes are returned.
Now the question:
- A non-blocking UDP socket also returns WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) if there is no data available. But if there is data availabe, does a non-blocking UDP socket return just some bytes, which could mean you only get half of a datagram OR does an UDP socket always return complete datagrams??
Edit:
What I mean with "half of a datagram" is: what happens if I call recv() in just the moment when the socket is currently receiving a datagram. In that moment there are some bytes in the buffer but the datagram isn't complete yet.
Your explanations and comments are appreciated. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
终于有一个借口从我的旧办公室盒子里翻出我的史蒂文斯书籍了。
如果缓冲区足够大,标准 Berkeley 套接字
recv()
和recvfrom()
函数将永远不会返回部分数据报。在内核完全接收并重新组装数据报之前,应用程序无法使用该数据报。有趣的是,这在今天已经不是什么大问题了,当提供的缓冲区太小时,其他网络编程接口不同意这种行为:
(史蒂文斯,《TCP/IP 插图》,第 1 卷,第 160 页)
Finally, an excuse to dig out my Stevens books from my old office boxes.
Provided the buffer is large enough, the standard Berkeley sockets
recv()
andrecvfrom()
functions will never return a partial datagram. The datagram is not available to the application until the kernel has completely received and reassembled the datagram.Interestingly, and this isn't much (any?) of an issue today, other network programming interfaces don't agree on the behavior when the provided buffer is too small:
(Stevens, TCP/IP Illustrated, Volume 1, p. 160)
是的,UDP 仅返回在该数据报中传输的数据。 UDP 不像 TCP 那样面向流。数据报是离散传输,并且不以任何方式真正与其他数据报相关联。这就是 TCP 的套接字选项是 SOCK_STREAM 的原因。
这样做的好处是您可以感受到单独的传输,而这对于 TCP 来说并不容易做到。
Yes, UDP just returns what data got transmitted in that one datagram. UDP is not stream-oriented like TCP. Datagrams are discrete transmissions, and are not really tied to other datagrams in any way. That's the reason the socket option for TCP is SOCK_STREAM.
The bright side of this is that you can get a sense of separate transmissions, which isn't really easy to do with TCP.
我相信您会得到精确的一个或零个数据报。但我现在无法支持这一点。也许其他人可以提供一个很好的参考?
编辑:我很确定你收不到半个数据报。数据报要么已到达缓冲区,要么尚未到达。
I believe you get precisely one or zero datagrams. But I can't back this up at this moment. Perhaps someone else could provide a good reference?
Edit: I'm pretty sure you can't receive half a datagram. Either the datagram has arrived in the in buffer, or it hasn't.