假设以下代码(为了简单起见,我在这里省略了必要的错误处理):
recv(sockfd, NULL, 0, MSG_PEEK);
recv(sockfd, buff, bufflen, 0);
在那种情况下:我能否确定在第一次调用 recv
之后整个数据报已经收到,因此第二次调用 recv
不会阻塞?
或者如果 IP 拆分数据报,第一个 recv
会在接收到该数据报的任何部分后立即返回,第二个 recv
将阻塞直到接收到整个数据报?
如果我将对 recv
的第一次调用替换为:
recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
我能确定这只会在接收到整个数据报后返回吗,否则 recv
将无法按照 的要求可靠地返回整个数据报的长度>MSG_TRUNC
?
最佳答案
Can I be sure that after the first call to recv the whole datagram is already received and therefore the second call to to recv will not block?
UDP 套接字以整个数据报为单位运行。在数据报可用之前,第一次调用不会返回,除非它返回 -1 以指示错误。 (TCP 套接字可能返回 0 以表示连接关闭,但 UDP 不会发生这种情况,因为它是无连接的。)
@Barmar 在评论中观察到,另一个线程或进程可以访问同一个套接字,原则上,可以在调用第一个 recv()
的线程或进程之前读取等待的数据报,但如果不是对你来说,随后的 recv()
实际上应该返回整个数据报,直到缓冲区中的可用空间量(消息中的任何多余字节都将丢失)。当然,这引出了您为什么要这样做的问题——您还不如跳过第一个 recv()
,并在必要时让第二个阻塞。
将 MSG_TRUNC
添加到标志中不会改变上述任何内容。同样,UDP 套接字以整个数据报为单位运行。唯一的区别是返回值给了你数据报的大小。 那 可能是额外的 recv()
调用的原因。
关于我可以确定在使用 MSG_PEEK 成功调用 recv 后立即执行的 UDP recv 不会阻塞吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44317781/