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