我可以确定在使用 MSG_PEEK 成功调用 recv 后立即执行的 UDP recv 不会阻塞吗?
Can I be sure that a UDP recv executed immediately after a successfull call to recv with MSG_PEEK will not block?
假设以下代码(为了简单起见,我在这里省略了必要的错误处理):
recv(sockfd, NULL, 0, MSG_PEEK);
recv(sockfd, buff, bufflen, 0);
在那种情况下:我可以确定在第一次调用 recv
之后整个数据报已经收到,因此第二次调用 recv
不会阻塞吗?
或者如果 IP 拆分数据报,第一个 recv
return 会在收到此数据报的任何部分后立即发生,第二个 recv
将阻塞直到收到整个数据报?
如果我将对 recv
的第一次调用替换为:
recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
我能否确定这只会 return 一旦收到整个数据报,否则 recv
无法可靠地 return 整个数据报的长度数据报,根据 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 套接字以整个数据报为单位运行。在数据报可用之前,第一次调用不会 return ,除非它 returns -1 指示错误。 (TCP 套接字可能 return 0 表示连接关闭,但 UDP 不会发生这种情况,因为它是无连接的。)
@Barmar 在评论中观察到,另一个线程或进程访问同一个套接字原则上可以在调用第一个 recv()
的线程或进程之前读取等待的数据报,但如果这不是问题然后,您随后的 recv()
实际上应该 return 整个数据报,最多达到缓冲区中可用的 space 数量(消息中任何多余的字节都将丢失)。当然,这引出了您为什么要这样做的问题——您还不如跳过第一个 recv()
,并在必要时让第二个阻塞。
将 MSG_TRUNC
添加到标志中不会改变上述任何内容。同样,UDP 套接字以整个数据报为单位运行。唯一的区别是 return 值给出了数据报的大小。 可能是额外 recv()
电话的原因。
假设以下代码(为了简单起见,我在这里省略了必要的错误处理):
recv(sockfd, NULL, 0, MSG_PEEK);
recv(sockfd, buff, bufflen, 0);
在那种情况下:我可以确定在第一次调用 recv
之后整个数据报已经收到,因此第二次调用 recv
不会阻塞吗?
或者如果 IP 拆分数据报,第一个 recv
return 会在收到此数据报的任何部分后立即发生,第二个 recv
将阻塞直到收到整个数据报?
如果我将对 recv
的第一次调用替换为:
recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
我能否确定这只会 return 一旦收到整个数据报,否则 recv
无法可靠地 return 整个数据报的长度数据报,根据 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 套接字以整个数据报为单位运行。在数据报可用之前,第一次调用不会 return ,除非它 returns -1 指示错误。 (TCP 套接字可能 return 0 表示连接关闭,但 UDP 不会发生这种情况,因为它是无连接的。)
@Barmar 在评论中观察到,另一个线程或进程访问同一个套接字原则上可以在调用第一个 recv()
的线程或进程之前读取等待的数据报,但如果这不是问题然后,您随后的 recv()
实际上应该 return 整个数据报,最多达到缓冲区中可用的 space 数量(消息中任何多余的字节都将丢失)。当然,这引出了您为什么要这样做的问题——您还不如跳过第一个 recv()
,并在必要时让第二个阻塞。
将 MSG_TRUNC
添加到标志中不会改变上述任何内容。同样,UDP 套接字以整个数据报为单位运行。唯一的区别是 return 值给出了数据报的大小。 可能是额外 recv()
电话的原因。