我可以确定在使用 MSG_PEEK 成功调用 recv 后立即执行的 UDP recv 不会阻塞吗?

标签 c linux sockets udp recv

假设以下代码(为了简单起见,我在这里省略了必要的错误处理):

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/

相关文章:

linux - 在 Linux 中截断文件的前 100MB

sockets - ovs-ofctl 不工作 - 连接被拒绝

创建可变大小矩阵

c - 使用 Windows 10 和 Cygwin 从命令提示符运行 c 程序

C 中的清屏

php - 如何配置可视化学习代码用docker识别php?

python - 使用Python子进程处理带括号的文件路径

c++ - 通过网络发送数据的常用方法是什么?

c - C中多线程后服务器上的段错误

c - 如何获取字符串中的每个字符?