2017-06-01 56 views
0

假设下面的代码(为简单起见,我省略了必要的错误处理):我可以确定在成功调用recv与MSG_PEEK后立即执行的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

如果在同一个套接字上有FD的另一个进程或线程,则不应该。在你做之前它可以读取数据包。 – Barmar

回答

3

我可以肯定的是,第一个电话后,recv的整个数据报已经收到 ,因此第二次调用到的recv不会 块?

UDP套接字以全数据报单元操作。第一次调用在数据报可用之前不会返回,除非它返回-1来指示错误。 (一个TCP套接字可能会返回0来表示连接的信号闭合,但这不会发生在UDP上,因为它是无连接的。)

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

MSG_TRUNC添加到标志不会改变上述任何情况。同样,UDP套接字以全数据报单元操作。唯一的区别是返回值给你数据报的大小。 可能是额外拨打recv()的原因。

+0

为什么这样的构造?我有两个线程,一个重复执行'recv',另一个重复执行'send',唯一的目的是让他们完成工作,而不必等到对方的阻塞套接字调用返回。为了简单起见,我想在互斥体下执行第二个'recv',以保护常用数据被锁定,这样第二个'recv'就可以写入这个公共数据。如果第二个'recv'没有阻塞,那就没问题。如果它可以阻止,那么整个想法就没有多大意义。 – gaazkam

相关问题