Skip to content

4.4 TCP 半连接队列和全连接队列

在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:

  • 半连接队列,也称 SYN 队列;

    • 实现:哈希表,在接收到第三次握手后,需要在队列里面找出存入的,所以哈希更快。
    • 存放收到 SYN 请求的 socket,并向客户端响应 SYN+ACK
  • 全连接队列,也称 accept 队列;

    • 实现:链表,不关心顺序, accept函数依次取走即可
    • 存放完成三次握手的连接
    • 进入这个队列之后,需要进程及时调用accept函数取走这个连接
      • 建立过程 accept 不参与,accept 是用来取走连接,如果全连接队伍为空,accept 阻塞
      • 没有被 accept 的连接,服务端只会返回 ACK 包,取走才能正常数据通信。
  • 两者都有最大长度限制,超过限制时,可以配置

    • 全连接:
      • 直接丢弃:客户端可能会重试,有空位可以连接上,但是连接不上不知道原因(默认)。
      • 回复RST:客户端知道原因,但是消耗资源发包。
    • 半连接:
      • 发送编码 cookie 给客户端:客户端跳过半连接,直接在第三次握手携带 cookie 进入全连接
        • 但是 cookie 编解码需要 CPU 资源,容易被攻击导致高负载。
      • 直接丢弃
  • 两者都可以通过参数设置进行扩容

  • 执行 listen 方法时,内核会自动会创建半连接队列和全连接队列,否则没有。

    • 如果服务端没有 listen 时客户端请求建立连接,会收到 RST 报文。
    • 没有 listen,客户端可以通过自连接或者客户端之间进行直接连接,但是很少会用到。

正在精进