2

因此,在 TCP 流的情况下,需要跟踪每次recv调用读取了多少消息。然后可以将部分读取拼凑在一起,最终可以正常接收消息。

但是对于 UDP 消息,应该如何处理部分读取(假设所有 UDP 消息都小到可以避免碎片)?由于部分消息的剩余数据似乎被丢弃,是否只是确保recvfrom返回与已发送的缓冲区大小相同的问题?如果存在差异,则意味着它是部分且有缺陷的消息,应该跳过它。

所以从概念上讲,虽然 TCP 示例需要一个循环,但 UDP 示例只需要一个 if 语句。

这个对吗?

4

4 回答 4

2

无法在 UDP 中进行部分读取。UDP 保证接收到的数据报与发送时一样,无论是否分段,因此必须先接收到整个数据报,然后才能读取它。

请参阅:http ://en.wikipedia.org/wiki/User_Datagram_Protocol ,您可以按照其中的参考资料获取更多官方资源。

至于读入缓冲区,您将需要一个至少与任何可能的数据报一样大小的缓冲区。或者另一种常见的方法是在数据报的开头附近包含数据报的大小,这样您就可以只读取这些字节来获取该数字,然后使用适当大小的缓冲区。

于 2013-10-21T04:47:52.860 回答
1

不正确。如果 recv() 返回与给定相同的长度,则消息是该长度或更大。没有办法说是哪个。正确的技术是使用比预期的最大可能数据报大一号的缓冲区。那么如果你得到那个长度,那一定是发件人的错误。

于 2013-10-21T00:03:19.427 回答
0

正确的。但是,只有在接收方事先知道发送方正在发送多少字节时,if 条件才会起作用。

于 2013-10-20T03:20:48.517 回答
0

如前所述,与这个问题密切相关的是,在将这些与数据报协议一起使用时,需要一种将适当大小(足够大)的缓冲区传递给 recv/recvmsg/recvfrom 的策略。对于 UDP,一个简单且 100% 可靠的方法是传递至少 65507 字节的缓冲区,即最大 UDP 有效负载大小。

但是,我更喜欢的一种更简洁的方法是明确询问 recv() 缓冲区需要多少字节。可以这样实现:

int buflen = recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (buflen < 0) {
    // handle error
    return;
}
uint8_t buf[buflen];
rxlen = recv(sockfd, buf, buflen, 0);
if (rxlen < 0) {
    // again, handle error
    return;
}
// Voila!  We've received our entire datagram
// without need to know the maximum datagram
// size before runtime.
于 2018-11-09T15:20:36.240 回答