Skip to content

Latest commit

 

History

History
26 lines (17 loc) · 2.51 KB

连接维护.md

File metadata and controls

26 lines (17 loc) · 2.51 KB

非阻塞IO连接维护

由于代码采用ET模式,这里主要讨论非阻塞IO的连接处理。

建立连接

  • 建立连接的过程

    通过socket、bind和listen系统调用后,系统会自动帮我们实现TCP连接的三次握手,所以在建立连接时,我们只需调用accept来检测是否存在已完成的连接队列,如果有则返回连接,没有则返回-1。由于采用ET模式,所以需要循环调用accept来接收连接直到返回值为-1。

  • 分析

    连接的建立不能无限的增长,其会受到文件描述符数量的限制,当连接满了,如果空等而不连接,那么就绪队列也满了后,会导致新连接无法建立。这里参考了muduo,准备一个空的文件描述符,accept后直接close,这样对端不会收到RST,至少可以知道服务器正在运行。在nginx中实现了延迟操作deferred accept,将accept的处理时机推迟到了三次握手成功完成后的连接上有可读数据后,才向listening socket的监听者投递读事件。这样一来,一旦 accept成功,Nginx 不用等待新接入连接上有读事件发生,便可以马上从其中读取请 求数据。这样,就提高了请求的处理效率

关闭连接

怎样实现一个优雅的关闭?

  • 对于client(非Keep-Alive),发送完请求后就可以shutdown写端,然后收到server发来的应答,最后close掉连接。也可以不shutdown写,等读完直接close。对于Keep-Alive的情况,client可以断开也可以不断开,server应该保证不主动断开。

  • 对于server则需要考虑不同的情况:

    • 当连接出现各种错误时,可以直接关闭
    • 短连接超时的请求,可以关闭
    • 长连接对方长时间没有请求,可以关闭
    • client发出Fin,server会收到0字节,通常不能判断client是close了还是shutdown,这时server应当把消息发完,然后才可以close(),如果对方调用的是close,会收到RST,server能感知到,就可以立即close了
    • 短连接正常结束,server通常不关闭
  • nginx实现了HTTP层的延时关闭,延迟关闭所要避免的就是在执行close后之后,却由于接收缓冲区中存放了客户端发来的数据,或者正在接收客户端的数据而导致发送RST复位报文异常终止连接所带来的负面影响。这个RST复位报文可能导致之前发送给客户端并且尚在网络或者客户端接收缓冲区的正常响应数据丢弃。在此基础上还可以继续使用TCP套接字实现的延迟关闭。