4.4 TCP 半连接队列和全连接队列
在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
半连接队列,也称 SYN 队列;
- 实现:哈希表,在接收到第三次握手后,需要在队列里面找出存入的,所以哈希更快。
- 存放收到 SYN 请求的 socket,并向客户端响应 SYN+ACK
全连接队列,也称 accept 队列;
- 实现:链表,不关心顺序, accept函数依次取走即可
- 存放完成三次握手的连接
- 进入这个队列之后,需要进程及时调用accept函数取走这个连接
- 建立过程 accept 不参与,accept 是用来取走连接,如果全连接队伍为空,accept 阻塞
- 没有被 accept 的连接,服务端只会返回 ACK 包,取走才能正常数据通信。
两者都有最大长度限制,超过限制时,可以配置
- 全连接:
- 直接丢弃:客户端可能会重试,有空位可以连接上,但是连接不上不知道原因(默认)。
- 回复
RST:客户端知道原因,但是消耗资源发包。
- 半连接:
- 发送编码 cookie 给客户端:客户端跳过半连接,直接在第三次握手携带 cookie 进入全连接
- 但是 cookie 编解码需要 CPU 资源,容易被攻击导致高负载。
- 直接丢弃
- 发送编码 cookie 给客户端:客户端跳过半连接,直接在第三次握手携带 cookie 进入全连接
- 全连接:
两者都可以通过参数设置进行扩容
执行
listen方法时,内核会自动会创建半连接队列和全连接队列,否则没有。- 如果服务端没有 listen 时客户端请求建立连接,会收到 RST 报文。
- 没有 listen,客户端可以通过自连接或者客户端之间进行直接连接,但是很少会用到。
