zoukankan      html  css  js  c++  java
  • 将网络描述符设置为非阻塞的场景

    很多服务器项目的实现中都有一句set_non_block(acceptfd),为什么要将acceptfd设为非阻塞?

    仔细想想,服务器使用socket_bind_listen三件套进行监听并将listenfd注册到epoll监控后,当有新的连接请求来临,会先通过内核协议栈完成TCP三次握手,这些完成三次握手的连接信息被维护在一个队列中(因为暂时还未被应用程序accept),此时epoll会感知到listenfd的可读事件并待应用程序调用accept返回这个连接的描述符。但是有一些特殊的情况如调用socket的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返回错误后检查这些错误码即可知道发生了什么。

    ps:尝试了如果在accept之前,客户端使用正常的close,也就是发送FIN报文的话,服务器accept会成功返回正常的acceptfd,只不过依然会触发读事件,且读事件处理时会读到0。也就是说正常的退出不会出现上述情况,非阻塞的accept主要是针对之前分析的某一端想提前拆链而主动发送RST报文的场景。

    参考:https://blog.csdn.net/yushiyaogg/article/details/38322701?utm_source=blogxgwz1

             https://www.cnblogs.com/JohnABC/p/6323046.html

  • 相关阅读:
    不可或缺 Windows Native (15)
    不可或缺 Windows Native (14)
    不可或缺 Windows Native (13)
    不可或缺 Windows Native (12)
    不可或缺 Windows Native (11)
    不可或缺 Windows Native (10)
    不可或缺 Windows Native (9)
    不可或缺 Windows Native (8)
    不可或缺 Windows Native (7)
    不可或缺 Windows Native (6)
  • 原文地址:https://www.cnblogs.com/joker1937/p/12796512.html
Copyright © 2011-2022 走看看