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

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

目录

  1. 概述
  2. [TCP 层整体架构](#TCP 层整体架构)
  3. [TCP 报文格式](#TCP 报文格式)
  4. [TCP 状态机](#TCP 状态机)
  5. 连接端点结构 (CONNECTION_ENDPOINT)
  6. [TDI_BUCKET 与 IRP 队列模型](#TDI_BUCKET 与 IRP 队列模型)
  7. 连接管理
  8. 监听与接受
  9. 数据发送路径
  10. 数据接收路径
  11. 事件处理器
  12. [lwIP 粘合层与 tcpip 线程模型](#lwIP 粘合层与 tcpip 线程模型)
  13. 断开与清理
  14. 工作流程图
  15. 数据流图
  16. 关键函数索引

1. 概述

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

1.1 架构特点

ReactOS 的 TCP 实现采用分层结构

  1. TDI 包装层 (ip/transport/tcp/):管理 CONNECTION_ENDPOINT、TDI_BUCKET IRP 队列,面向 TDI 接口
  2. lwIP 粘合层 (ip/lwip_glue/tcp.c):通过 LibTCP* 函数桥接到 lwIP
  3. 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):

c 复制代码
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 标志位

c 复制代码
/* 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):

c 复制代码
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 选项

c 复制代码
#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 请求:

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

使用 TdiBucketLookasideList 后备列表分配:

c 复制代码
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):

c 复制代码
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
相关推荐
SendTomo2 小时前
send.wang私传网:P2P直连传大文件首选工具
javascript·网络·网络协议·webrtc·p2p
llllll1522 小时前
HTTP协议全解:从报文结构到HTTPS加密原理
网络协议·http·https
caimouse2 小时前
tcpip.sys 传输层 (UDP) 详细分析
网络·网络协议·udp
珠***格13 小时前
双碳目标下:四可装置如何助力光伏消纳与碳数据上报
网络·人工智能·分布式·安全·边缘计算
mounter62514 小时前
绕过主机:通过 Devmem TCP 运行 RDMA 应用
网络·网络协议·tcp/ip·rdma·devmem
我星期八休息15 小时前
网络编程—网络层
开发语言·前端·网络·人工智能·智能路由器
科力锐品牌君15 小时前
行业龙头|科力锐全链路防勒索 + 多中心容灾方案,构筑河南翔宇医疗业务安全闭环!
网络·数据库·分布式·安全·数据安全·备份
2401_8685347816 小时前
C语言与C++在基础语法上的区别
网络·网络协议
黄俊懿17 小时前
【架构师从入门到进阶】第五章:DNS&CDN&网关优化思路——第三节:CDN扩展-多地址直连
网络·计算机网络·架构·系统架构·cdn·dns·架构设计