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

时间:2017-06-01 22:01:13

标签: 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的要求可靠地返回整个数据报的长度?

1 个答案:

答案 0 :(得分:3)

  

我可以确定在第一次调用recv之后整个数据报是   已收到,因此对recv的第二次调用不会   方框?

UDP套接字以整数据报单位运行。在数据报可用之前,第一次调用将不会返回,除非它返回-1表示错误。 (TCP套接字可能返回0表示连接信号关闭,但UDP不会发生这种情况,因为它是无连接的。)

@Barmar在评论中注意到,另一个可以访问同一个套接字的线程或进程原则上可以在调用第一个recv()之前读取等待数据报,但是如果那不是你的问题那么后续的recv()确实应该返回整个数据报,直到缓冲区中可用的空间量(消息中的任何多余字节都会丢失)。当然这引出了为什么要这样做的问题 - 你可能也跳过了第一个recv(),如果有必要,让第二个阻止。

向标志添加MSG_TRUNC不会改变上述任何内容。同样,UDP套接字以整数据报单位运行。唯一的区别是返回值为您提供数据报的大小。 可能是额外recv()电话的原因。