最近在和同时讨论一个问题,TCP recv函数到底时什么时候返回,结束阻塞的呢?各有各的看法、有的说是检测到窗口为0时返回,有的说是系统内核发出的接收完毕信号,有的说是收到给定的大小结束的.........
一开始我也不确定到底哪个正确,为了追寻正确的答案,去看了下linux 系统源码tcp实现的部分,找到了在接收这块的逻辑,最终确定下来了recv函数的返回时机。
recv的返回时机有很多,比如关闭了连接或者出错等都会返回,这些我们都不看,不考虑,只看正常情况下的返回。
函数 int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags);
当调用recv(阻塞模式)函数后,正常情况下内部逻辑如下:
情况1. 当检测到接收缓冲队列中没有数据时候,一直循环阻塞
情况2.当检测到接收缓冲队列中有数据,则开始读取数据,写入到用户缓冲buf中,清除掉接收队列中已经读取到的数据,写完队列中的一包再写下一包,直到写入len大小数据,返回。这时队列中可能正好空了,也可能还有数据待下次读取。这时recv返回的大小=len
情况3:当检测到接收缓冲队列中有数据,则开始读取数据,写入到用户缓冲buf中,清除掉接收队列中已经读取到的数据。写完队列中的一包再写下一包,当检测队列一个循环,都没有数据了,但是还没有超过len大小,返回,这时recv返回的大小<len
以上是对正