Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 这是处理UDP消息部分读取的正确方法吗?_C_Tcp_Udp_Partial - Fatal编程技术网

C 这是处理UDP消息部分读取的正确方法吗?

C 这是处理UDP消息部分读取的正确方法吗?,c,tcp,udp,partial,C,Tcp,Udp,Partial,因此,在TCP流的情况下,需要跟踪每个recv调用读取的消息量。然后可以将部分读取拼接在一起,最终可以接收到消息 但是对于UDP消息,应该如何处理部分读取(假设所有UDP消息都足够小以避免碎片)?由于部分消息的剩余数据似乎已被丢弃,是否只需确保recvfrom返回与已发送的缓冲区相同的大小?如果存在差异,则表示这是一条不完整且有缺陷的消息,应该跳过它 因此,从概念上讲,虽然TCP示例需要一个循环,但UDP示例只需要一个if语句 这正确吗?正确。然而,只有当接收方提前知道发送方发送了多少字节时,i

因此,在TCP流的情况下,需要跟踪每个
recv
调用读取的消息量。然后可以将部分读取拼接在一起,最终可以接收到消息

但是对于UDP消息,应该如何处理部分读取(假设所有UDP消息都足够小以避免碎片)?由于部分消息的剩余数据似乎已被丢弃,是否只需确保
recvfrom
返回与已发送的缓冲区相同的大小?如果存在差异,则表示这是一条不完整且有缺陷的消息,应该跳过它

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


这正确吗?

正确。然而,只有当接收方提前知道发送方发送了多少字节时,if条件才会起作用。

不正确。如果recv()返回的长度与给定的长度相同,则消息的长度等于或大于该长度。没有办法知道是哪个。正确的方法是使用比预期的最大数据报大一倍的缓冲区。那么,如果您得到了该长度,那么发送方一定有错误。

无法在UDP中执行部分读取。UDP保证接收的数据报与发送的数据报相同,不完整也不完整,因此必须先接收整个数据报,然后才能读取

请参阅:,您可以按照其中的参考资料获取更多官方来源


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

如前所述,与此问题密切相关的是,在使用数据报协议时,需要一种策略,将适当大小(足够大)的缓冲区传递给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.
int buflen=recv(sockfd,NULL,0,MSG_PEEK | MSG_TRUNC);
如果(buflen<0){
//处理错误
返回;
}
uint8_t buf[buflen];
rxlen=recv(sockfd,buf,buflen,0);
如果(rxlen<0){
//同样,处理错误
返回;
}
//瞧!我们已经收到了所有的数据报
//无需知道最大数据报
//运行前的大小。

没错。感谢
数据报–数据包是单独发送的,只有在到达时才检查完整性。数据包具有明确的边界,在接收时将予以遵守,这意味着接收器套接字上的读取操作将产生一条原始发送的完整消息。
这是否意味着当我接收到数据报时,我可以始终确保它的大小和内容与原始发送的相同?也就是说,唯一可能发生的“错误”是当数据报被完全删除时?在这种情况下,recvfrom返回读取大小有什么意义?我并不是故意刁难,我只是想了解…@c00kiemonster您需要长度,因为您通常不知道发送了什么。@c00kiemonster,因为发送方可以发送不同大小的数据报-这完全取决于发送方的数据报有多少字节,因此我说“需要一个缓冲区,至少任何可能的数据报的大小。”[对于您的应用程序]“-如果您收到的数据报大于您的应用程序支持的最大数据报,则可能是恶意的或有缺陷的对等方,因此只需丢弃它。”…缓冲区比预期的最大数据报大一个”,这是一种技术,另一种技术是使用与预期最大值相同大小的缓冲区,并将该大小包含在您自己的标头中。