为什么
recv
系统调用不能一直阻塞到所有数据都接收完毕?每当我看到一个 recv
调用时,它总是在一个 while 循环中,不断调用 recv
直到所有的数据都在那里。为什么不一开始就让 recv
阻塞呢?recv
系统调用不能一直阻塞到所有数据都接收完毕?每当我看到一个 recv
调用时,它总是在一个 while 循环中,不断调用 recv
直到所有的数据都在那里。为什么不一开始就让 recv
阻塞呢?MSG_WAITALL
标志请求 recv 阻塞,直到接收到所有数据。然而,如果有信号到达,已经执行了一些工作(即接收部分数据)的系统调用是不会自动重新启动以接收剩余数据的。因此,即使使用了 MSG_WAITALL
,在缓冲区填满之前,recv 调用仍可能返回,在这种情况下,你必须准备处理这些情况。鉴于此,许多人选择循环而不烦恼于像 MSG_WAITALL
这样的不知名标志。
至于为什么默认情况下会这样,有几个原因:
但最重要的是,由于你必须准备处理部分缓冲区 任何情况,因此强制人们默认处理它是很好的,这样他们会尽早发现循环中的错误-而不是让它们一直隐藏,直到信号在不幸的时刻到达。
在大多数情况下,你不知道“所有数据”的数量有多少。例如,如果你正在接收行定向协议的数据,则一行可能长达10个字节或65个字节。
您可以将套接字标志更改为阻塞或非阻塞。您的具体情况实际上与阻塞或非阻塞无关。
默认情况下,使网络功能按照您描述的方式运行毫无意义 - 如果流永远不会结束...那么程序永远不会结束吗?乍一看,这似乎不是健康的默认行为。
阅读http://www.scottklement.com/rpg/socktut/nonblocking.html以熟悉阻塞和非阻塞IO。