为什么在收到所有数据之前不会阻止recv?

jas*_*ogd 8 c python sockets network-programming

为什么在recv收到所有数据之前系统调用只是阻塞?每当我看到一个recv呼叫时,它就会在一个while循环中继续呼叫,recv直到所有数据都存在.为什么不recv首先阻止?

bdo*_*lan 9

您可以请求recv块,直到收到所有数据,并带有MSG_WAITALL标志.但是,如果信号到达,则执行某些工作(即接收部分数据)的系统调用无法自动重新启动以接收其余信号.因此,即使有MSG_WAITALL,也可能在缓冲区已满之前可能会返回recv调用,并且您必须准备好处理这些情况.鉴于此,许多人只是选择循环,而不是打扰鲜为人知的标志,如MSG_WAITALL.

至于为什么默认情况是这样的,有几个原因可以想到:

  • 您经常希望接收部分读取.例如,如果您正在逐步显示数据,或者您将数据代理到其他地方,或者如果数据太大,则无法立即将整个数据缓冲在内存中.毕竟,如果您只是立即写入文件,您是否关心将它分成200个写入而不是150个?
  • 有时您甚至不知道一开始就需要多少数据.考虑telnet协议,这在BSD套接字API设计时很流行.你通常会在同一时间内接收的字节屈指可数,没有长度字段告诉你多少数据的期望,而且你需要显示的数据的时候了.在此处填充缓冲区之前阻塞是没有意义的.与使用SMTP或IMAP等面向行的协议一样,在收到所有命令之前,您不知道命令的持续时间.
  • recv通常用于数据报套接字,它接收单个数据报,即使它比提供的缓冲区小得多.流式套接字的自然扩展是尽可能多地返回,而无需等待.

但最重要的,因为你需要做好准备,以应对部分缓冲无论如何,这是很好的,迫使人们在默认情况下处理它,所以他们转起来的错误在他们的循环早期-而不是让他们仍然隐藏,直到信号到了一个不幸的时刻.