非阻塞accept

先说一下为什么要使用非阻塞的accept.如果我们使用select或者epoll对listenfd进行监控,正常情况下,三次握手完成之后,服务器端维护了一个队列来保存这些连接,select或者epoll会触发listenfd的可读事件来待程序员调用accept返回这个连接的描述字.但是有一些特殊的情况在本博客中的TCP连接中的close和shutdown一文中提到了一种情况.调用close函数,并且(l_onoff = 1, l_linger =0),这种情况是为了尽快回收套接字资源,不发送FIN报文,发送的时RST报文,套接字直接进入CLOSE状态,不会进入TIMEWAIT状态.这种情况就要求非阻塞accept的存在.

假设一种情况,当客户度端发起连接,完成了三次握手之后.但是此时服务器端因为很忙碌,还没有调用accept函数来确认这个连接.此时客户端使用close函数关闭了连接,注意此时客户端发送的是RST报文而不是FIN报文,所以该链接就在内核中就被断开了,但是此时用户层并不知道这种变化,如果此时服务器端经过epoll触发的listenfd调用阻塞的accept,那么由于连接已经被取消,所以accept就会被阻塞,那么其他注册在epoll中的fd就不能被即使处理,所以我们需要将listenfd设置为非阻塞的,保证完成accept时非阻塞的.

当设置accept是非阻塞的时,如果有连接存在,那么accept正常返回.如果时没有连接存在,或者像上述所说的连接被取消了,那么会返回不同的错误码,我们只需要在accept返回错误后检查这些错误码,如果是这两种情况,把它当做征程情况不用处理即可.


ps:尝试了如果在accept之前,使用正常的close,也就是发送正常的FIN报文的话,accept会返回成功,返回正常的socketfd,在下一次读事件时会读到0.也就是说正常的退出不会出现上述情况,不需要非阻塞的accept来处理.


你可能感兴趣的:(计算机网络)