什么是全连接半连接
在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
- 半连接队列,也称 Listen 队列;
- 全连接队列,也称 accept 队列;
工作原理
每一个socket执行listen
时,内核会自动创建一个半连接队列和全连接队列。
服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到 半连接 队列,并向客户端响应 SYN+ACK,此时服务端处于SYN_RCYD状态。
接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,并将其添加到 全连接 队列,等待进程调用 accept 函数时把连接取出来。
所以,accept
方法只是为了从全连接队列中拿出一条连接,本身跟三次握手几乎毫无关系。
半连接队列(listen队列):
-
服务器listen socket收到客户端SYN请求后,放入这个队列等待连接建立。
-
队列长度即
listen()
函数形参中的backlog参数大小。 -
记录了完成了客户端到服务器SYN报文的连接请求。
-
队列满时,新SYN请求会被丢弃。
全连接队列(accept队列):
- 记录了完成TCP三次握手,但还未被
accept()
取出的连接。 - 这些连接完成了SYN和SYN+ACK报文的发送。
- 当应用程序调用
accept()
时,从这个队列中取出完成连接。 - 队列满时,已完成的连接会被丢弃。
- 队列长度由内核根据需要动态调整。
不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回 RST 包(在TCP通信中,RST包用于终止连接或者中断双方之间的通信。当一方希望立即中断TCP连接时,它可以发送一个RST包给对方)。
意义
- 减轻服务器
accept
压力,提高连接效率
- 将三次握手分阶段进行,不需要立即
accept
,减少服务器立即处理连接的压力。
- 防止同时大量连接淹没服务器
- 通过队列缓冲和丢弃机制,防止过多连接集中淹没服务器。