TCP建立连接的过程
listen
listen的工作主要是申请和初始化接收队列,包括全连接队列和半连接队列。全/半连接队列是三次握手中重要的数据结构,有它服务端才能响应客户端的三次握手
全连接队列
全连接是链表,最大长度为listen传入的backlog和net.core.somaxconn之间较小的值。
半连接队列
半链接的数据结构为哈希表,长度为min(backlog,somaxconn,tcp_max_syn_backlog)+1再向上取到2的N次幂。
connect
客户端在执行connect函数的时候,会把本地socket状态设置为TCP_SYN_SENT,选择一个可用的端口,接着发出SYN握手请求并启动重传定时器。(一个客户端最大能建立的连接数不是65535,只要服务器足够多,单机能发财百万条连接)
连接建立过程总结
sequenceDiagram
autonumber
participant C as 客户端
participant S as 服务端 TCP/IP 协议栈
participant Q1 as 半连接队列
participant Q2 as 全连接队列
participant A as 服务端应用程序
Note over S,A: listen()<br/>申请并初始化接收队列
C->>C: 选择可用的本地端口
C->>S: SYN
Note left of C: connect()<br/>1. 发送 SYN 握手请求<br/>2. 启动重传定时器
S->>Q1: 创建半连接记录
S-->>C: SYN + ACK
Note right of S: 1. 发送 SYN+ACK<br/>2. 进入半连接队列<br/>3. 启动重传定时器
C->>C: 清除 SYN 重传定时器
C->>C: 设置连接状态为已连接
C->>S: ACK
S->>S: 创建新的已连接 socket
S->>Q1: 从半连接队列移除
S->>Q2: 加入全连接队列
A->>S: accept()
S->>Q2: 从全连接队列取出 socket
S-->>A: 返回已连接 socket