• 将网络描述符设置为非阻塞的场景


    很多服务器项目的实现中都有一句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

  • 相关阅读:
    加密算法
    oracle利用正则表达式判断字符串只包含数字
    LINUX下用数据泵导入导出(IMPDP、EXPDP)
    Oracle删除用户和表空间
    SQL脚本
    Oracle 查询库中所有表名、字段名、字段名说明,查询表的数据条数、表名、中文表名、
    Oracle修改表Table所属表空间及Clob、Blob字段的处理
    Linux下修改Oracle监听地址
    批量删除默认用户
    oracle创建新用户和用户表空间
  • 原文地址:https://www.cnblogs.com/joker1937/p/12796512.html
Copyright © 2020-2023  润新知