云计算百科
云计算领域专业知识百科平台

tcpip.sys 传输层 (TCP) 详细分析

tcpip.sys 传输层 (TCP) 详细分析

目录

  • 概述
  • TCP 层整体架构
  • TCP 报文格式
  • TCP 状态机
  • 连接端点结构 (CONNECTION_ENDPOINT)
  • TDI_BUCKET 与 IRP 队列模型
  • 连接管理
  • 监听与接受
  • 数据发送路径
  • 数据接收路径
  • 事件处理器
  • lwIP 粘合层与 tcpip 线程模型
  • 断开与清理
  • 工作流程图
  • 数据流图
  • 关键函数索引

  • 1. 概述

    TCP (Transmission Control Protocol,传输控制协议) 是 TCP/IP 协议栈中面向连接的可靠传输协议,提供有序、可靠、全双工的字节流服务。在 ReactOS tcpip.sys 中,TCP 层位于 TDI 接口与 IP 层之间。

    1.1 架构特点

    ReactOS 的 TCP 实现采用分层结构:

  • TDI 包装层 (ip/transport/tcp/):管理 CONNECTION_ENDPOINT、TDI_BUCKET IRP 队列,面向 TDI 接口
  • lwIP 粘合层 (ip/lwip_glue/tcp.c):通过 LibTCP* 函数桥接到 lwIP
  • lwIP 核心 (lwip/src/core/tcp*.c):实现完整的 TCP 状态机、拥塞控制、重传等
  • 1.2 TCP 特性

    特性说明
    面向连接 三次握手建立连接,四次挥手断开
    可靠传输 确认 (ACK) + 超时重传
    有序交付 序号机制保证字节流有序
    流量控制 滑动窗口 + 窗口通告
    拥塞控制 慢启动 + 拥塞避免 + 快速重传/恢复
    全双工 双方可同时收发
    字节流 无报文边界,面向字节流

    2. TCP 层整体架构

    2.1 三层结构

    ┌─────────────────────────────────────────────────────────┐
    │ TDI 接口层 (上层: AFD.sys / TDI 客户端) │
    │ TDI_CONNECT / TDI_LISTEN / TDI_ACCEPT │
    │ TDI_SEND / TDI_RECEIVE / TDI_DISCONNECT │
    └──────────────────────┬──────────────────────────────────┘

    ┌──────────────────────▼──────────────────────────────────┐
    │ TCP 包装层 (ip/transport/tcp/) ←★ │
    │ │
    │ tcp.c : TCPSocket/TCPConnect/TCPSendData/TCPReceiveData
    │ accept.c : TCPListen/TCPAccept/TCPAbortListenForSocket │
    │ event.c : TCP*EventHandlers / Flush*Queue │
    │ if.c : 接口更新 (TCPUpdateInterface*) │
    │ │
    │ 核心对象: CONNECTION_ENDPOINT + TDI_BUCKET 队列 │
    └──────────────────────┬──────────────────────────────────┘
    │ LibTCP* 调用
    ┌──────────────────────▼──────────────────────────────────┐
    │ lwIP 粘合层 (ip/lwip_glue/tcp.c) │
    │ LibTCPSocket/LibTCPConnect/LibTCPSend/LibTCPListen… │
    │ 通过 tcpip_callback 排队到 tcpip 线程 │
    └──────────────────────┬──────────────────────────────────┘
    │ lwIP raw API
    ┌──────────────────────▼──────────────────────────────────┐
    │ lwIP TCP 核心 (lwip/src/core/tcp.c/tcp_in.c/tcp_out.c) │
    │ struct tcp_pcb (协议控制块) │
    │ 状态机 / 重传 / 拥塞控制 / 滑动窗口 │
    └──────────────────────┬──────────────────────────────────┘
    │ LibIPInsertPacket / tcp_output
    ┌──────────────────────▼──────────────────────────────────┐
    │ IP 网络层 │
    └─────────────────────────────────────────────────────────┘

    2.2 源码文件

    源文件职责
    ip/transport/tcp/tcp.c 核心:TCPSocket/TCPConnect/TCPSendData/TCPReceiveData/TCPDisconnect
    ip/transport/tcp/accept.c 监听/接受:TCPListen/TCPAccept/TCPCheckPeerForAccept
    ip/transport/tcp/event.c 事件处理:TCPEventHandlers、FlushQueue
    ip/transport/tcp/if.c 接口绑定:TCPUpdateInterfaceIPInformation/LinkStatus
    ip/lwip_glue/tcp.c lwIP 桥接:LibTCP* 系列函数
    include/tcpcore.h 保留的 Linux 2.4.20 移植结构 (sk_buff/tcp_opt)
    include/tcp.h TCP 头、CONNECTION_ENDPOINT 声明

    2.3 历史:Linux 移植 vs lwIP

    注意: ReactOS 早期将 Linux 内核 2.4.20 的 TCP 实现移植到 include/tcpcore.h
    (含 struct sk_buff / struct tcp_opt / struct sock 完整结构)。
    当前实际使用的 TCP 协议实现是 lwIP 2.x (通过 LibTCP* 粘合层),
    tcpcore.h 仍保留在头文件树中但不再是活动实现。


    3. TCP 报文格式

    定义在 [tcp.h](file:///d:/reactos/drivers/network/tcpip/include/tcp.h#L15-L25):

    typedef struct TCPv4_HEADER {
    USHORT SourcePort; // 源端口 (2B)
    USHORT DestinationPort; // 目的端口 (2B)
    ULONG SequenceNumber; // 序号 (4B)
    ULONG AckNumber; // 确认号 (4B)
    UCHAR DataOffset; // 数据偏移 (高 4 位, 单位 32 位字)
    UCHAR Flags; // 标志位 (低 6 位)
    USHORT Window; // 接收窗口 (2B)
    USHORT Checksum; // 校验和 (2B)
    USHORT Urgent; // 紧急指针 (2B)
    } TCPv4_HEADER, *PTCPv4_HEADER;

    0 1 2 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Source Port | Destination Port |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Sequence Number |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Acknowledgment Number |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Data | |C|E|U|A|P|R|S|F| |
    | Offset| Rsvd |W|C|R|C|S|S|Y|I| Window |
    | | |R|E|G|K|H|T|N|N| |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Checksum | Urgent Pointer |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    3.1 标志位

    /* tcpdef.h 中的 TCP 标志 */
    #define TCP_FIN 0x01 // 结束连接
    #define TCP_SYN 0x02 // 同步序号 (连接建立)
    #define TCP_RST 0x04 // 重置连接
    #define TCP_PSH 0x08 // 推送数据
    #define TCP_ACK 0x10 // 确认
    #define TCP_URG 0x20 // 紧急

    3.2 伪头 (TCPv4_PSEUDO_HEADER)

    定义在 [tcp.h](file:///d:/reactos/drivers/network/tcpip/include/tcp.h#L38-L44):

    typedef struct TCPv4_PSEUDO_HEADER {
    ULONG SourceAddress; // 源 IP
    ULONG DestinationAddress; // 目的 IP
    UCHAR Zero; // 保留
    UCHAR Protocol; // 6 (TCP)
    USHORT TCPLength; // TCP 段长度
    } TCPv4_PSEUDO_HEADER, *PTCPv4_PSEUDO_HEADER;

    3.3 TCP 选项

    #define TCPOPT_END_OF_LIST 0x0 // 选项结束
    #define TCPOPT_NO_OPERATION 0x1 // 无操作
    #define TCPOPT_MAX_SEG_SIZE 0x2 // 最大段大小 (MSS)
    #define TCPOPTLEN_MAX_SEG_SIZE 0x4


    4. TCP 状态机

    TCP 共有 11 种状态(lwIP tcp_state_str):

    +———+
    | CLOSED |
    +—-+—-+
    |
    主动打开/被动打开
    |
    +—-v—-+
    | LISTEN |
    +—-+—-+
    | 收到 SYN
    +—-v—-+
    | SYN_RCVD |
    +—-+—-+
    | 发送 SYN+ACK
    |
    主动打开 | 同时打开
    +—-v—-+ +—-v—-+
    | SYN_SENT+——–> SYN_RCVD |
    +—-+—-+ +—-+—-+
    | |
    | 收到 SYN+ACK | 收到 ACK
    +——–+——–+
    |
    +——v——+
    | ESTABLISHED |
    +——+——+
    |
    +————+————+
    | 主动关闭 | 被动关闭 |
    ▼ ▼
    +———+ +———–+
    |FIN_WAIT_1| | CLOSE_WAIT|
    +—-+—-+ +—–+—–+
    | | 关闭
    +—-v—-+ +—-v—-+
    |FIN_WAIT_2| | LAST_ACK|
    +—-+—-+ +—-+—-+
    | |
    +—-v—-+ |
    |TIME_WAIT| |
    +—-+—-+ |
    | |
    +—-v—-+ |
    | CLOSED |<——–+
    +———+

    4.1 关键状态

    状态说明
    LISTEN 监听,等待 SYN
    SYN_SENT 已发送 SYN,等待 SYN+ACK
    SYN_RCVD 已收到 SYN,已发送 SYN+ACK
    ESTABLISHED 连接建立,数据传输
    FIN_WAIT_1/2 主动关闭等待
    CLOSE_WAIT 被动关闭等待应用关闭
    TIME_WAIT 2MSL 等待 (60 秒)

    5. 连接端点结构 (CONNECTION_ENDPOINT)

    CONNECTION_ENDPOINT 是 TCP 层的核心对象,定义在 [titypes.h](file:///d:/reactos/drivers/network/tcpip/include/titypes.h)。

    5.1 结构概览

    CONNECTION_ENDPOINT

    ├── 对象管理
    │ ├── LONG RefCount // 引用计数
    │ ├── OBJECT_FREE_ROUTINE Free // 释放函数 (ConnectionFree)
    │ └── ERESOURCE Resource // 对象锁

    ├── 地址绑定
    │ ├── PADDRESS_FILE AddressFile // 关联的地址文件
    │ ├── PVOID SocketContext // lwIP tcp_pcb 指针
    │ └── PCONNECTION_ENDPOINT Next // 地址文件的连接链表

    ├── 请求队列 (TDI_BUCKET 链表)
    │ ├── LIST_ENTRY ConnectRequest // 连接请求
    │ ├── LIST_ENTRY ListenRequest // 监听请求
    │ ├── LIST_ENTRY AcceptRequest // 接受请求
    │ ├── LIST_ENTRY ReceiveRequest // 接收请求
    │ ├── LIST_ENTRY SendRequest // 发送请求
    │ └── LIST_ENTRY ShutdownRequest // 断开请求

    ├── 数据队列
    │ ├── LIST_ENTRY PacketQueue // 收到的 pbuf 队列 (lwIP)
    │ ├── PLIST_ENTRY SendDataQueue // 待发送数据
    │ └── PLIST_ENTRY FastSendDataQueue

    └── 状态
    ├── KEVENT DisconnectEvent
    ├── KTIMER DisconnectTimer
    └── KSPIN_LOCK DisconnectLock

    5.2 TDI_BUCKET — 请求桶

    TDI_BUCKET 封装了一个挂起的 TDI 请求:

    typedef struct _TDI_BUCKET {
    LIST_ENTRY Entry; // 队列链接
    TDI_REQUEST Request; // TDI 请求 (句柄+完成回调+上下文)
    PCONNECTION_ENDPOINT AssociatedEndpoint; // 关联的连接端点
    NTSTATUS Status; // 完成状态
    ULONG_PTR Information; // 传输的字节数/信息
    } TDI_BUCKET, *PTDI_BUCKET;

    使用 TdiBucketLookasideList 后备列表分配:

    ExInitializeNPagedLookasideList(&TdiBucketLookasideList,
    NULL, NULL, 0,
    sizeof(TDI_BUCKET), TDI_BUCKET_TAG, 0);

    5.3 收发窗口 (AFD 中定义)

    AFD 层维护 FCB->Send/Recv 窗口,TCP 层通过 TDI 接口与之交互。


    6. TDI_BUCKET 与 IRP 队列模型

    6.1 请求挂起模型

    用户态 IRP (TDI_SEND)


    TCP 层:
    ├─ 分配 TDI_BUCKET
    ├─ 保存完成回调 (Complete) 和上下文 (Context)
    ├─ InsertTailList(&Connection->SendRequest, &Bucket->Entry)
    └─ 返回 STATUS_PENDING

    ▼ (lwIP 事件触发时)
    事件处理器:
    ├─ RemoveHeadList(&Connection->SendRequest)
    ├─ 执行操作 (LibTCPSend)
    ├─ Bucket->Status = 结果
    ├─ Bucket->Information = 字节数
    └─ CompleteBucket → BucketCompletionWorker
    └─ 调用 TDI 完成回调 → 完成用户 IRP

    6.2 CompleteBucket — 完成请求

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L37-L50):

    CompleteBucket(Connection, Bucket, Synchronous)
    ├─ ReferenceObject(Connection)
    ├─ Bucket->AssociatedEndpoint = Connection
    ├─ Synchronous → BucketCompletionWorker 直接执行
    └─ 异步 → ChewCreate(BucketCompletionWorker, Bucket) 排队

    6.3 BucketCompletionWorker — 完成工作项

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L21-L35):

    BucketCompletionWorker(Context)
    ├─ Bucket = Context
    ├─ Complete = Bucket->Request.RequestNotifyObject
    ├─ Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information)
    │ └─ 通常为 DispDataRequestComplete → IoCompleteRequest
    ├─ DereferenceObject(Bucket->AssociatedEndpoint)
    └─ ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket)

    6.4 Flush*Queue 系列

    函数功能
    FlushReceiveQueue 以状态完成所有挂起接收
    FlushSendQueue 完成所有挂起发送
    FlushShutdownQueue 完成所有挂起断开
    FlushConnectQueue 完成所有挂起连接
    FlushListenQueue 完成所有挂起监听
    FlushAllQueues 全部完成 (连接终止时)

    7. 连接管理

    7.1 TCPSocket — 创建 socket

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L153):

    TCPSocket(Connection, Family, Type, Proto)

    ├─ LockObject(Connection)
    ├─ 调用 LibTCPSocket(Connection) → 创建 lwIP tcp_pcb
    ├─ 设置回调:
    │ tcp_arg(pcb, Connection)
    │ tcp_err(pcb, InternalErrorEventHandler)
    │ (连接建立后设置 tcp_recv/tcp_sent/tcp_accept)
    ├─ Connection->SocketContext = pcb
    └─ 返回

    7.2 TCPConnect — 发起连接

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L301-L424):

    TCPConnect(Connection, ConnInfo, ReturnInfo, Complete, Context)

    ├─ LockObject(Connection)
    ├─ 解析远端地址 (TA_IP_ADDRESS → ip_addr_t)

    ├─ 分配本地端口:
    │ LocalAddress = 地址文件地址
    │ 端口未指定 → TCPAllocatePort(动态)

    ├─ 创建 TDI_BUCKET 挂入 ConnectRequest

    ├─ LibTCPConnect(Connection, &ipaddr, port)
    │ └─ lwIP: tcp_connect(pcb, ipaddr, port, InternalConnectEventHandler)

    ├─ 返回 STATUS_PENDING

    └─ 连接完成 → TCPConnectEventHandler

    7.3 LibTCPConnect — lwIP 桥接

    在 [tcp.c 粘合层](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L621-L635):

    LibTCPConnect(Connection, ipaddr, port)

    ├─ 分配 lwip_callback_msg
    ├─ 填充 Input.Connect { Connection, IpAddress, Port }
    ├─ tcpip_callback_with_block(LibTCPConnectCallback, msg, 1)
    │ └─ 在 tcpip 线程中执行:
    │ tcp_arg(pcb, Connection)
    │ tcp_recv(pcb, InternalRecvEventHandler)
    │ tcp_sent(pcb, InternalSendEventHandler)
    │ tcp_connect(pcb, ipaddr, port, InternalConnectEventHandler)
    │ msg->Output.Connect.Error = …
    ├─ KeWaitForSingleObject(&msg->Event) // 等待 tcpip 线程完成
    └─ 返回错误码

    7.4 TCPConnectEventHandler — 连接完成

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L419-L441):

    TCPConnectEventHandler(arg, err)
    ├─ Connection = arg
    ├─ 遍历 ConnectRequest 队列:
    │ Bucket->Status = TCPTranslateError(err)
    │ CompleteBucket(Connection, Bucket, FALSE)
    └─ 完成所有挂起的连接请求


    8. 监听与接受

    8.1 TCPListen — 监听

    在 [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L47-L105):

    TCPListen(Connection, Backlog)

    ├─ 解析本地绑定地址:
    │ AddressToBind = AddressFile->Address
    │ Port = AddressFile->Port

    ├─ LibTCPBind(Connection, &AddressToBind, Port)
    │ └─ tcp_bind(pcb, ipaddr, port)

    ├─ 端口未指定 (0):
    │ ├─ TCPGetSockAddress 获取实际端口
    │ ├─ TCPAllocatePort 分配端口
    │ └─ AddressFile->Port = AllocatedPort

    ├─ Connection->SocketContext = LibTCPListen(Connection, Backlog)
    │ └─ tcp_listen(pcb) + tcp_accept(pcb, InternalAcceptEventHandler)

    └─ 返回

    8.2 TCPAccept — 接受连接

    在 [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L139):

    TCPAccept(Request, Listener, Connection, Complete, Context)

    ├─ 分配 TDI_BUCKET
    ├─ Bucket->AssociatedEndpoint = Connection (接受新连接的 socket)
    ├─ 挂入 Listener->ListenRequest

    └─ 返回 STATUS_PENDING
    └─ 新连接到达 → TCPAcceptEventHandler

    8.3 TCPAcceptEventHandler — 接受完成

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L230-L291):

    TCPAcceptEventHandler(arg, newpcb)

    ├─ Connection = arg (Listener)
    ├─ 遍历 ListenRequest 队列:
    │ ├─ TCPCheckPeerForAccept(newpcb, Request):
    │ │ └─ LibTCPGetPeerName → 填充远端地址
    │ │
    │ ├─ 成功:
    │ │ ├─ 释放原 socket 上下文 (LibTCPClose 旧的 pcb)
    │ │ ├─ Bucket->AssociatedEndpoint->SocketContext = newpcb
    │ │ └─ LibTCPAccept(newpcb, listen_pcb, AssociatedEndpoint)
    │ │ └─ tcp_recv/tcp_sent/tcp_err/tcp_poll 设置
    │ │ └─ 通知 AFD 完成 accept
    │ │
    │ └─ CompleteBucket(Connection, Bucket, FALSE)
    │ └─ 完成用户 IRP
    └─ 只接受一个连接 (break)

    8.4 TCPAbortListenForSocket — 中止监听

    在 [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L107-L137):

    TCPAbortListenForSocket(Listener, Connection)
    ├─ 遍历 Listener->ListenRequest
    ├─ 找到关联 Connection 的 Bucket:
    │ ├─ 移除 + 释放
    │ └─ 返回 TRUE
    └─ 返回 FALSE


    9. 数据发送路径

    9.1 TCPSendData — 发送入口

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L579-L630):

    TCPSendData(Connection, Buffer, DataSize, DataUsed, Flags, Complete, Context)

    ├─ 分配 TDI_BUCKET
    ├─ Bucket->Request.RequestNotifyObject = Complete
    ├─ Bucket->Request.RequestContext = Context

    ├─ 挂入 Connection->SendRequest

    ├─ 尝试立即发送:
    │ LibTCPSend(Connection, Buffer, DataSize, &sent, TRUE)
    │ ├─ 成功 → 完成 Bucket (返回已发送字节数)
    │ └─ 失败 (STATUS_PENDING) → 保持挂起

    └─ 返回 STATUS_PENDING / 立即完成

    9.2 LibTCPSend — lwIP 发送

    在 [tcp.c 粘合层](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L556-L590):

    LibTCPSend(Connection, dataptr, len, sent, safe)

    ├─ 分配 lwip_callback_msg
    ├─ tcpip_callback_with_block(LibTCPSendCallback, msg, 1)
    │ └─ tcpip 线程中:
    │ Error = tcp_write(pcb, dataptr, len, TCP_WRITE_FLAG_COPY)
    │ 成功 → tcp_output(pcb)
    │ msg->Output.Send.Error = Error
    │ msg->Output.Send.Information = len
    ├─ 等待事件
    ├─ *sent = Information
    └─ 返回错误码

    9.3 TCPSendEventHandler — 发送事件

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L293-L377),由 lwIP tcp_sent 回调触发(发送窗口有空间时):

    TCPSendEventHandler(arg, space)

    ├─ Connection = arg
    ├─ 遍历 SendRequest 队列:
    │ ├─ NdisQueryBuffer(Irp->MdlAddress) → 用户发送缓冲
    │ ├─ LibTCPSend(Connection, SendBuffer, SendLen, &BytesSent, TRUE)
    │ ├─ STATUS_PENDING → 放回队列头部, 停止
    │ ├─ 成功 → Bucket->Information = BytesSent
    │ └─ CompleteBucket (完成用户 IRP)

    ├─ 全部完成后:
    │ ├─ FlushShutdownQueue(STATUS_SUCCESS) // 完成待处理的断开
    │ └─ KeCancelTimer(DisconnectTimer)

    └─ DereferenceObject


    10. 数据接收路径

    10.1 TCPReceive — IP 层入口

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L192-L206),作为 IPRegisterProtocol(IPPROTO_TCP, TCPReceive) 注册:

    TCPReceive(Interface, IPPacket)

    └─ LibIPInsertPacket(Interface->TCPContext, IPPacket->Header, TotalSize)
    └─ 将 IP 数据包送入 lwIP 的 netif 输入 (tcpip 线程)

    10.2 LibIPInsertPacket — 注入 lwIP

    在 [ip.c 粘合层](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/ip.c):

    LibIPInsertPacket(ifarg, data, size)

    ├─ 创建 pbuf (PBUF_RAW, 引用数据)
    ├─ 排队到 tcpip 线程输入队列
    │ └─ tcpip_thread 处理 → netif->input → tcp_input
    │ └─ lwIP 处理 TCP 段 (校验/序号/状态机)
    │ └─ 数据到达 → 调用 InternalRecvEventHandler
    └─ 完成

    10.3 InternalRecvEventHandler → TCPRecvEventHandler

    lwIP 数据到达时调用注册的 tcp_recv 回调(粘合层中):

    InternalRecvEventHandler(arg, pcb, p, err)

    ├─ Connection = arg
    ├─ 将 pbuf 挂入 Connection->PacketQueue:
    │ LibTCPEnqueuePacket(Connection, p)
    │ tcp_recved(pcb, p->tot_len) // 通知 lwIP 数据已取走

    └─ 调用外部处理器:
    TCPRecvEventHandler(Connection) // event.c

    10.4 TCPRecvEventHandler — 接收事件

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L379-L417):

    TCPRecvEventHandler(arg)

    ├─ Connection = arg
    ├─ 遍历 ReceiveRequest 队列:
    │ ├─ NdisQueryBuffer(Irp->MdlAddress) → 用户接收缓冲
    │ ├─ LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer,
    │ │ RecvLen, &Received)
    │ │ └─ 从 PacketQueue 解包 pbuf, 复制数据到用户缓冲
    │ ├─ STATUS_PENDING → 放回队列头部, 停止 (无数据)
    │ ├─ 成功 → Bucket->Information = Received
    │ └─ CompleteBucket (完成用户 IRP)

    └─ 完成

    10.5 TCPReceiveData — TDI 接收入口

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L528-L577):

    TCPReceiveData(Connection, Buffer, ReceiveLength, BytesReceived,
    ReceiveFlags, Complete, Context)

    ├─ 分配 TDI_BUCKET 挂入 ReceiveRequest

    ├─ 尝试立即取数据:
    │ LibTCPGetDataFromConnectionQueue → 有数据则完成
    │ STATUS_PENDING → 保持挂起等待 TCPRecvEventHandler

    └─ 返回


    11. 事件处理器

    11.1 事件处理器总览

    lwIP 通过回调驱动 TCP 层,粘合层将回调转发给 event.c 的处理器:

    lwIP 回调 粘合层 事件处理器 (event.c)
    ───────── ────── ─────────────────
    tcp_connect 完成 → InternalConnectEventHandler → TCPConnectEventHandler
    tcp_accept 新连接 → InternalAcceptEventHandler → TCPAcceptEventHandler
    tcp_recv 数据到达 → InternalRecvEventHandler → TCPRecvEventHandler
    tcp_sent 可发送 → InternalSendEventHandler → TCPSendEventHandler
    tcp_err 错误/关闭 → InternalErrorEventHandler → TCPFinEventHandler
    tcp_poll 周期轮询 → InternalPollEventHandler → (keepalive/超时)

    11.2 TCPFinEventHandler — 连接终止

    在 [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L181-L228):

    TCPFinEventHandler(arg, err)

    ├─ Status = TCPTranslateError(err)
    ├─ FlushAllQueues(Connection, Status) // 完成所有挂起请求

    ├─ 从地址文件连接链表移除:
    │ ├─ 是首连接 → AddressFile->Connection = Next
    │ ├─ 是监听器 → AddressFile->Listener = NULL
    │ └─ 遍历查找 → 从链中移除

    ├─ DereferenceObject(AddressFile)
    ├─ Connection->AddressFile = NULL
    └─ 完成

    11.3 TCPTranslateError — 错误码转换

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L267-L299),将 lwIP err_t 转换为 NTSTATUS:

    err_t → NTSTATUS
    ERR_OK (0) → STATUS_SUCCESS
    ERR_MEM (-1) → STATUS_INSUFFICIENT_RESOURCES
    ERR_BUF (-2) → STATUS_BUFFER_TOO_SMALL
    ERR_TIMEOUT(-3)→ STATUS_TIMEOUT
    ERR_RTE (-4) → STATUS_NETWORK_UNREACHABLE
    ERR_INPROGRESS→ STATUS_PENDING
    ERR_VAL (-6) → STATUS_INVALID_PARAMETER
    ERR_WOULDBLOCK→ STATUS_CANT_WAIT
    ERR_USE (-8) → STATUS_ADDRESS_ALREADY_EXISTS
    ERR_ABRT (-10) → STATUS_LOCAL_DISCONNECT
    ERR_RST (-11) → STATUS_REMOTE_DISCONNECT
    ERR_CLSD (-12) → STATUS_FILE_CLOSED
    ERR_CONN (-13) → STATUS_INVALID_CONNECTION
    ERR_IF (-15) → STATUS_UNEXPECTED_NETWORK_ERROR


    12. lwIP 粘合层与 tcpip 线程模型

    12.1 线程模型

    lwIP 要求所有 raw API 调用在 tcpip 线程 中执行:

    LibTCPXxx (调用线程)

    │ 1. 分配 lwip_callback_msg { Event, Input, Output }
    │ 2. 填充 Input 参数
    │ 3. tcpip_callback_with_block(LibTCPXxxCallback, msg, 1)
    │ │
    │ ▼ (排队到 tcpip 线程)
    │ tcpip 线程: LibTCPXxxCallback(msg)
    │ ├─ 调用 lwIP raw API (tcp_connect/tcp_write/…)
    │ ├─ 填充 msg->Output
    │ └─ KeSetEvent(&msg->Event)

    │ 4. KeWaitForSingleObject(&msg->Event) // 等待完成
    │ 5. 读取 Output

    └─ 返回结果

    12.2 lwip_callback_msg

    定义在 [lwip_glue.h](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/lwip_glue.h#L24-L92):

    struct lwip_callback_msg
    {
    KEVENT Event; // 同步事件

    union { // 输入参数
    struct { PVOID Arg; } Socket;
    struct { struct tcp_pcb* pcb; } FreeSocket;
    struct { PCONNECTION_ENDPOINT Connection; ip_addr_t *IpAddress; u16_t Port; } Bind;
    struct { PCONNECTION_ENDPOINT Connection; u8_t Backlog; } Listen;
    struct { PCONNECTION_ENDPOINT Connection; void *Data; u16_t DataLength; } Send;
    struct { PCONNECTION_ENDPOINT Connection; ip_addr_t *IpAddress; u16_t Port; } Connect;
    struct { PCONNECTION_ENDPOINT Connection; int shut_rx; int shut_tx; } Shutdown;
    struct { PCONNECTION_ENDPOINT Connection; int Callback; } Close;
    } Input;

    union { // 输出结果
    struct { struct tcp_pcb *NewPcb; } Socket;
    struct { err_t Error; } Bind;
    struct { struct tcp_pcb *NewPcb; } Listen;
    struct { err_t Error; u32_t Information; } Send;
    struct { err_t Error; } Connect;
    struct { err_t Error; } Shutdown;
    struct { err_t Error; } Close;
    } Output;
    };

    12.3 LibTCP* 函数清单

    函数lwIP 调用功能
    LibTCPSocket tcp_new 创建 PCB
    LibTCPFreeSocket tcp_close 关闭 PCB
    LibTCPBind tcp_bind 绑定本地地址端口
    LibTCPListen tcp_listen + tcp_accept 进入监听
    LibTCPSend tcp_write + tcp_output 发送数据
    LibTCPConnect tcp_connect 发起连接
    LibTCPShutdown tcp_shutdown 关闭读写
    LibTCPClose tcp_close 关闭
    LibTCPGetPeerName 读 PCB 字段 获取远端地址
    LibTCPGetHostName 读 PCB 字段 获取本地地址
    LibTCPAccept 设置回调 设置新 PCB 回调
    LibTCPSetNoDelay tcp_nagle_disable 禁用 Nagle
    LibTCPGetSocketStatus 读 state 获取状态
    LibTCPEnqueuePacket pbuf 管理 入队接收数据
    LibTCPGetDataFromConnectionQueue pbuf 读取 出队复制数据
    LibIPInsertPacket netif input 注入 IP 包

    13. 断开与清理

    13.1 TCPDisconnect — TDI 断开

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L426-L526):

    TCPDisconnect(Connection, Flags, Timeout, ConnInfo, ReturnInfo, Complete, Context)

    ├─ 解析 Flags:
    │ TDI_DISCONNECT_ABORT:
    │ │ └─ LibTCPShutdown(Connection, 1, 1) // 立即中止 (RST)
    │ │
    │ TDI_DISCONNECT_RELEASE:
    │ │ └─ LibTCPShutdown(Connection, 0, 1) // 只关发送 (FIN)
    │ │
    │ 其他 (正常):
    │ └─ LibTCPShutdown(Connection, 0, 1)
    │ └─ 挂起 ShutdownRequest 直到发送完成

    ├─ 设置 DisconnectTimer (超时强制完成)

    └─ 完成或挂起

    13.2 TCPClose — 关闭

    在 [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L177-L190):

    TCPClose(Connection)
    └─ LibTCPClose(Connection, FALSE, TRUE)
    └─ tcp_close(pcb) → lwIP 发送 FIN/释放

    13.3 连接资源释放 (ConnectionFree)

    ConnectionFree(Object)
    ├─ Connection = Object
    ├─ 清理 PacketQueue (释放 pbuf)
    ├─ LibTCPFreeSocket(SocketContext) // 关闭 lwIP PCB
    └─ ExFreePool(Connection)


    14. 工作流程图

    14.1 TCP 连接建立 (三次握手)

    远端

    lwIP tcpip线程

    TCP层(tcpip.sys)

    应用程序

    远端

    lwIP tcpip线程

    TCP层(tcpip.sys)

    应用程序

    #mermaid-svg-rexOxnyITE46znnG{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rexOxnyITE46znnG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rexOxnyITE46znnG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rexOxnyITE46znnG .error-icon{fill:#552222;}#mermaid-svg-rexOxnyITE46znnG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rexOxnyITE46znnG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rexOxnyITE46znnG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rexOxnyITE46znnG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rexOxnyITE46znnG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rexOxnyITE46znnG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rexOxnyITE46znnG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rexOxnyITE46znnG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rexOxnyITE46znnG .marker.cross{stroke:#333333;}#mermaid-svg-rexOxnyITE46znnG svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rexOxnyITE46znnG p{margin:0;}#mermaid-svg-rexOxnyITE46znnG .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rexOxnyITE46znnG text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-rexOxnyITE46znnG .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rexOxnyITE46znnG .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-rexOxnyITE46znnG .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-rexOxnyITE46znnG .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-rexOxnyITE46znnG #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-rexOxnyITE46znnG .sequenceNumber{fill:white;}#mermaid-svg-rexOxnyITE46znnG #sequencenumber{fill:#333;}#mermaid-svg-rexOxnyITE46znnG #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-rexOxnyITE46znnG .messageText{fill:#333;stroke:none;}#mermaid-svg-rexOxnyITE46znnG .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rexOxnyITE46znnG .labelText,#mermaid-svg-rexOxnyITE46znnG .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-rexOxnyITE46znnG .loopText,#mermaid-svg-rexOxnyITE46znnG .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-rexOxnyITE46znnG .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rexOxnyITE46znnG .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-rexOxnyITE46znnG .noteText,#mermaid-svg-rexOxnyITE46znnG .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-rexOxnyITE46znnG .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rexOxnyITE46znnG .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rexOxnyITE46znnG .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rexOxnyITE46znnG .actorPopupMenu{position:absolute;}#mermaid-svg-rexOxnyITE46znnG .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-rexOxnyITE46znnG .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rexOxnyITE46znnG .actor-man circle,#mermaid-svg-rexOxnyITE46znnG line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-rexOxnyITE46znnG :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    第一次握手

    connect() (TDI_CONNECT)

    分配本地端口 + 创建 TDI_BUCKET

    LibTCPConnect (排队到 tcpip 线程)

    发送 SYN (tcp_connect)

    收到 SYN+ACK

    发送 ACK (第二次/第三次握手)

    InternalConnectEventHandler (err=ERR_OK)

    TCPConnectEventHandler 完成所有连接请求

    连接成功 (IoCompleteRequest)

    14.2 TCP 数据发送流程

    #mermaid-svg-8ganwPQbVs6NqoPE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8ganwPQbVs6NqoPE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8ganwPQbVs6NqoPE .error-icon{fill:#552222;}#mermaid-svg-8ganwPQbVs6NqoPE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8ganwPQbVs6NqoPE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8ganwPQbVs6NqoPE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8ganwPQbVs6NqoPE .marker.cross{stroke:#333333;}#mermaid-svg-8ganwPQbVs6NqoPE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8ganwPQbVs6NqoPE p{margin:0;}#mermaid-svg-8ganwPQbVs6NqoPE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8ganwPQbVs6NqoPE .cluster-label text{fill:#333;}#mermaid-svg-8ganwPQbVs6NqoPE .cluster-label span{color:#333;}#mermaid-svg-8ganwPQbVs6NqoPE .cluster-label span p{background-color:transparent;}#mermaid-svg-8ganwPQbVs6NqoPE .label text,#mermaid-svg-8ganwPQbVs6NqoPE span{fill:#333;color:#333;}#mermaid-svg-8ganwPQbVs6NqoPE .node rect,#mermaid-svg-8ganwPQbVs6NqoPE .node circle,#mermaid-svg-8ganwPQbVs6NqoPE .node ellipse,#mermaid-svg-8ganwPQbVs6NqoPE .node polygon,#mermaid-svg-8ganwPQbVs6NqoPE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8ganwPQbVs6NqoPE .rough-node .label text,#mermaid-svg-8ganwPQbVs6NqoPE .node .label text,#mermaid-svg-8ganwPQbVs6NqoPE .image-shape .label,#mermaid-svg-8ganwPQbVs6NqoPE .icon-shape .label{text-anchor:middle;}#mermaid-svg-8ganwPQbVs6NqoPE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8ganwPQbVs6NqoPE .rough-node .label,#mermaid-svg-8ganwPQbVs6NqoPE .node .label,#mermaid-svg-8ganwPQbVs6NqoPE .image-shape .label,#mermaid-svg-8ganwPQbVs6NqoPE .icon-shape .label{text-align:center;}#mermaid-svg-8ganwPQbVs6NqoPE .node.clickable{cursor:pointer;}#mermaid-svg-8ganwPQbVs6NqoPE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8ganwPQbVs6NqoPE .arrowheadPath{fill:#333333;}#mermaid-svg-8ganwPQbVs6NqoPE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8ganwPQbVs6NqoPE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8ganwPQbVs6NqoPE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8ganwPQbVs6NqoPE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8ganwPQbVs6NqoPE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8ganwPQbVs6NqoPE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8ganwPQbVs6NqoPE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8ganwPQbVs6NqoPE .cluster text{fill:#333;}#mermaid-svg-8ganwPQbVs6NqoPE .cluster span{color:#333;}#mermaid-svg-8ganwPQbVs6NqoPE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8ganwPQbVs6NqoPE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8ganwPQbVs6NqoPE rect.text{fill:none;stroke-width:0;}#mermaid-svg-8ganwPQbVs6NqoPE .icon-shape,#mermaid-svg-8ganwPQbVs6NqoPE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8ganwPQbVs6NqoPE .icon-shape p,#mermaid-svg-8ganwPQbVs6NqoPE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8ganwPQbVs6NqoPE .icon-shape .label rect,#mermaid-svg-8ganwPQbVs6NqoPE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8ganwPQbVs6NqoPE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8ganwPQbVs6NqoPE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8ganwPQbVs6NqoPE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    应用 send

    TDI_SEND → TCPSendData

    分配 TDI_BUCKET

    挂入 SendRequest 队列

    LibTCPSend

    排队 tcpip_callback

    tcpip 线程: tcp_write + tcp_output

    发送窗口有空间?

    构造 TCP 段 → IP 层发送

    等待 tcp_sent 事件

    tcp_sent 回调 → InternalSendEventHandler

    TCPSendEventHandler

    从 SendRequest 取 Bucket

    LibTCPSend 发送下一批

    CompleteBucket 完成用户 IRP

    应用 send 返回

    14.3 TCP 数据接收流程

    #mermaid-svg-ptEeDvx6XZn7ApUY{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ptEeDvx6XZn7ApUY .error-icon{fill:#552222;}#mermaid-svg-ptEeDvx6XZn7ApUY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ptEeDvx6XZn7ApUY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ptEeDvx6XZn7ApUY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ptEeDvx6XZn7ApUY .marker.cross{stroke:#333333;}#mermaid-svg-ptEeDvx6XZn7ApUY svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ptEeDvx6XZn7ApUY p{margin:0;}#mermaid-svg-ptEeDvx6XZn7ApUY .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster-label text{fill:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster-label span{color:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster-label span p{background-color:transparent;}#mermaid-svg-ptEeDvx6XZn7ApUY .label text,#mermaid-svg-ptEeDvx6XZn7ApUY span{fill:#333;color:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY .node rect,#mermaid-svg-ptEeDvx6XZn7ApUY .node circle,#mermaid-svg-ptEeDvx6XZn7ApUY .node ellipse,#mermaid-svg-ptEeDvx6XZn7ApUY .node polygon,#mermaid-svg-ptEeDvx6XZn7ApUY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ptEeDvx6XZn7ApUY .rough-node .label text,#mermaid-svg-ptEeDvx6XZn7ApUY .node .label text,#mermaid-svg-ptEeDvx6XZn7ApUY .image-shape .label,#mermaid-svg-ptEeDvx6XZn7ApUY .icon-shape .label{text-anchor:middle;}#mermaid-svg-ptEeDvx6XZn7ApUY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ptEeDvx6XZn7ApUY .rough-node .label,#mermaid-svg-ptEeDvx6XZn7ApUY .node .label,#mermaid-svg-ptEeDvx6XZn7ApUY .image-shape .label,#mermaid-svg-ptEeDvx6XZn7ApUY .icon-shape .label{text-align:center;}#mermaid-svg-ptEeDvx6XZn7ApUY .node.clickable{cursor:pointer;}#mermaid-svg-ptEeDvx6XZn7ApUY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ptEeDvx6XZn7ApUY .arrowheadPath{fill:#333333;}#mermaid-svg-ptEeDvx6XZn7ApUY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ptEeDvx6XZn7ApUY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ptEeDvx6XZn7ApUY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ptEeDvx6XZn7ApUY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ptEeDvx6XZn7ApUY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ptEeDvx6XZn7ApUY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster text{fill:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY .cluster span{color:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ptEeDvx6XZn7ApUY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ptEeDvx6XZn7ApUY rect.text{fill:none;stroke-width:0;}#mermaid-svg-ptEeDvx6XZn7ApUY .icon-shape,#mermaid-svg-ptEeDvx6XZn7ApUY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ptEeDvx6XZn7ApUY .icon-shape p,#mermaid-svg-ptEeDvx6XZn7ApUY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ptEeDvx6XZn7ApUY .icon-shape .label rect,#mermaid-svg-ptEeDvx6XZn7ApUY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ptEeDvx6XZn7ApUY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ptEeDvx6XZn7ApUY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ptEeDvx6XZn7ApUY :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    IP 层 → TCPReceive

    LibIPInsertPacket

    创建 pbuf 注入 netif

    tcpip 线程: tcp_input

    lwIP 校验/序号处理

    tcp_recv 回调

    InternalRecvEventHandler

    LibTCPEnqueuePacket 挂入 PacketQueue

    tcp_recved 通知 lwIP

    TCPRecvEventHandler

    有挂起的 ReceiveRequest?

    LibTCPGetDataFromConnectionQueue

    复制数据到用户 MDL 缓冲

    CompleteBucket 完成 IRP

    应用 recv 返回

    数据留在队列等待

    14.4 监听与接受流程

    #mermaid-svg-Pf82DBbYmNKxP41n{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Pf82DBbYmNKxP41n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Pf82DBbYmNKxP41n .error-icon{fill:#552222;}#mermaid-svg-Pf82DBbYmNKxP41n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Pf82DBbYmNKxP41n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Pf82DBbYmNKxP41n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Pf82DBbYmNKxP41n .marker.cross{stroke:#333333;}#mermaid-svg-Pf82DBbYmNKxP41n svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Pf82DBbYmNKxP41n p{margin:0;}#mermaid-svg-Pf82DBbYmNKxP41n .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Pf82DBbYmNKxP41n .cluster-label text{fill:#333;}#mermaid-svg-Pf82DBbYmNKxP41n .cluster-label span{color:#333;}#mermaid-svg-Pf82DBbYmNKxP41n .cluster-label span p{background-color:transparent;}#mermaid-svg-Pf82DBbYmNKxP41n .label text,#mermaid-svg-Pf82DBbYmNKxP41n span{fill:#333;color:#333;}#mermaid-svg-Pf82DBbYmNKxP41n .node rect,#mermaid-svg-Pf82DBbYmNKxP41n .node circle,#mermaid-svg-Pf82DBbYmNKxP41n .node ellipse,#mermaid-svg-Pf82DBbYmNKxP41n .node polygon,#mermaid-svg-Pf82DBbYmNKxP41n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Pf82DBbYmNKxP41n .rough-node .label text,#mermaid-svg-Pf82DBbYmNKxP41n .node .label text,#mermaid-svg-Pf82DBbYmNKxP41n .image-shape .label,#mermaid-svg-Pf82DBbYmNKxP41n .icon-shape .label{text-anchor:middle;}#mermaid-svg-Pf82DBbYmNKxP41n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Pf82DBbYmNKxP41n .rough-node .label,#mermaid-svg-Pf82DBbYmNKxP41n .node .label,#mermaid-svg-Pf82DBbYmNKxP41n .image-shape .label,#mermaid-svg-Pf82DBbYmNKxP41n .icon-shape .label{text-align:center;}#mermaid-svg-Pf82DBbYmNKxP41n .node.clickable{cursor:pointer;}#mermaid-svg-Pf82DBbYmNKxP41n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Pf82DBbYmNKxP41n .arrowheadPath{fill:#333333;}#mermaid-svg-Pf82DBbYmNKxP41n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Pf82DBbYmNKxP41n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Pf82DBbYmNKxP41n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Pf82DBbYmNKxP41n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Pf82DBbYmNKxP41n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Pf82DBbYmNKxP41n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Pf82DBbYmNKxP41n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Pf82DBbYmNKxP41n .cluster text{fill:#333;}#mermaid-svg-Pf82DBbYmNKxP41n .cluster span{color:#333;}#mermaid-svg-Pf82DBbYmNKxP41n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Pf82DBbYmNKxP41n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Pf82DBbYmNKxP41n rect.text{fill:none;stroke-width:0;}#mermaid-svg-Pf82DBbYmNKxP41n .icon-shape,#mermaid-svg-Pf82DBbYmNKxP41n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Pf82DBbYmNKxP41n .icon-shape p,#mermaid-svg-Pf82DBbYmNKxP41n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Pf82DBbYmNKxP41n .icon-shape .label rect,#mermaid-svg-Pf82DBbYmNKxP41n .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Pf82DBbYmNKxP41n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Pf82DBbYmNKxP41n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Pf82DBbYmNKxP41n :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    应用 listen

    TDI_LISTEN → TCPListen

    LibTCPBind 绑定地址

    LibTCPListen 进入监听

    tcp_accept 注册回调

    应用 accept → TCPAccept

    挂入 ListenRequest 队列

    远端 SYN 到达

    lwIP 完成三次握手

    tcp_accept 回调 → TCPAcceptEventHandler

    TCPCheckPeerForAccept 获取远端地址

    成功?

    释放旧 socket 上下文

    SocketContext = newpcb

    LibTCPAccept 设置新 PCB 回调

    CompleteBucket 完成 accept IRP

    以错误完成

    应用 accept 返回新 socket


    15. 数据流图

    15.1 完整的发送数据流

    应用程序 send(buf)


    TDI_SEND IRP → DispTdiSend → TCPSendData

    │ TDI_BUCKET { Complete, Context } 挂入 SendRequest


    LibTCPSend → tcpip 线程 → tcp_write(pcb, buf, len)

    │ lwIP 将数据加入发送队列, 构造 TCP 段:
    │ ┌──────────────────────────────────────┐
    │ │ TCP 头 (20B) │
    │ │ SourcePort / DestPort │
    │ │ Seq = snd_nxt │
    │ │ Ack = rcv_nxt │
    │ │ Flags = ACK | PSH │
    │ │ Window = rcv_wnd │
    │ │ Checksum = TCP 伪头校验和 │
    │ ├──────────────────────────────────────┤
    │ │ 数据 (应用负载) │
    │ └──────────────────────────────────────┘


    tcp_output → IP 层 (IPTransmitPacket)


    网络接口层 → LAN → NDIS → 网卡

    ▼ (远端 ACK 到达)
    lwIP tcp_in → tcp_sent 回调


    TCPSendEventHandler → 完成用户 IRP


    send() 返回

    15.2 完整的接收数据流

    网卡 → NDIS → 网络接口层 → IP 层


    TCPReceive → LibIPInsertPacket → pbuf


    tcpip 线程: tcp_input

    │ 校验和验证 → 序号检查 → 状态机处理


    数据到达 → tcp_recv 回调 (InternalRecvEventHandler)

    ├─ pbuf 挂入 Connection->PacketQueue
    ├─ tcp_recved (滑动窗口更新)
    └─ TCPRecvEventHandler


    从 ReceiveRequest 取 Bucket


    LibTCPGetDataFromConnectionQueue
    │ 从 pbuf 复制到用户缓冲 (MDL)

    CompleteBucket → 完成 TDI IRP


    DispDataRequestComplete → IoCompleteRequest


    recv() 返回数据

    15.3 TDI_BUCKET 生命周期

    创建 (TCPSendData/TCPReceiveData/TCPConnect…)
    │ ExAllocateFromNPagedLookasideList(TdiBucketLookasideList)

    挂起 (InsertTailList → PendingIrpList)
    │ 等待 lwIP 事件

    触发 (TCP*EventHandlers)
    │ RemoveHeadList

    完成 (CompleteBucket)
    │ BucketCompletionWorker
    │ ├─ Complete(Context, Status, Information) → 完成用户 IRP
    │ ├─ DereferenceObject(Connection)
    │ └─ ExFreeToNPagedLookasideList(Bucket)

    释放


    16. 关键函数索引

    16.1 TCP 核心 (tcp.c)

    函数位置说明
    TCPStartup [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L208-L240) 初始化:端口集/Bucket 池/LibIP/注册协议
    TCPShutdown [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L243-L265) 清理
    TCPSocket [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L153) 创建 socket (LibTCPSocket)
    TCPConnect [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L301-L424) 发起连接
    TCPDisconnect [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L426-L526) 断开 (FIN/RST)
    TCPSendData [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L579-L630) 发送数据
    TCPReceiveData [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L528-L577) 接收数据
    TCPReceive [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L192-L206) IP 层接收入口
    TCPClose [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L177-L190) 关闭连接
    TCPTranslateError [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L267-L299) err_t → NTSTATUS
    TCPAllocatePort / TCPFreePort [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L636-L655) 端口管理
    TCPRemoveIRP [tcp.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c#L695) 取消 IRP

    16.2 监听/接受 (accept.c)

    函数位置说明
    TCPListen [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L47-L105) 监听 (LibTCPBind+Listen)
    TCPAccept [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L139) 接受连接
    TCPCheckPeerForAccept [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L17-L43) 获取远端地址
    TCPAbortListenForSocket [accept.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c#L107-L137) 中止监听

    16.3 事件处理 (event.c)

    函数位置说明
    TCPConnectEventHandler [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L419-L441) 连接完成
    TCPAcceptEventHandler [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L230-L291) 新连接接受
    TCPSendEventHandler [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L293-L377) 可发送
    TCPRecvEventHandler [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L379-L417) 数据到达
    TCPFinEventHandler [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L181-L228) 连接终止
    CompleteBucket [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L37-L50) 完成请求桶
    BucketCompletionWorker [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L21-L35) 完成工作项
    FlushAllQueues [event.c](file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/event.c#L156-L179) 清空所有队列

    16.4 lwIP 粘合层 (lwip_glue/tcp.c)

    函数位置说明
    LibTCPSocket [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L336) tcp_new
    LibTCPConnect [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L621-L635) tcp_connect
    LibTCPSend [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L556-L590) tcp_write+tcp_output
    LibTCPBind [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L414-L440) tcp_bind
    LibTCPListen [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L469-L495) tcp_listen
    LibTCPShutdown [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c) tcp_shutdown
    LibTCPClose [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c) tcp_close
    LibTCPEnqueuePacket [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L73-L84) pbuf 入队
    LibTCPGetDataFromConnectionQueue [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c#L100) pbuf 出队复制
    LibIPInsertPacket [ip.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/ip.c) 注入 IP 包
    LibTCPAccept [tcp.c 粘合](file:///d:/reactos/drivers/network/tcpip/ip/lwip_glue/tcp.c) 设置新 PCB 回调

    附录 A:保留的 Linux 移植结构 (tcpcore.h)

    include/tcpcore.h 保留了 Linux 内核 2.4.20 的完整移植:

    结构说明
    struct sk_buff 套接字缓冲区 (head/data/tail/end 指针)
    struct skb_shared_info skb 共享信息 (分片)
    struct sk_buff_head skb 队列
    struct tcp_opt TCP 选项/状态 (rcv_nxt/snd_nxt/snd_una/snd_wnd 等)
    struct sock socket 状态

    这些结构保留但不再是活动实现(当前使用 lwIP 的 struct tcp_pcb)。

    附录 B:参考文档

    • [tcpip传输层UDP分析](file:///d:/reactos/doc/tcpip传输层UDP分析.md) — UDP 传输层
    • [tcpip网络层IP分析](file:///d:/reactos/doc/tcpip网络层IP分析.md) — IP 网络层
    • [TCPIP 驱动分析](file:///d:/reactos/doc/TCPIP_驱动分析.md) — tcpip.sys 整体
    • [lwIP 源码](file:///d:/reactos/drivers/network/tcpip/lwip/) — lwIP 协议栈
    • RFC 793 — Transmission Control Protocol
    • RFC 1122 — Requirements for Internet Hosts
    • RFC 2581 — TCP Congestion Control
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » tcpip.sys 传输层 (TCP) 详细分析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!