Reactos 第 10 章 网络操作 — 10.4 Socket的无连接通信

第 10 章 网络操作 --- 10.4 Socket的无连接通信

本节剖析 UDP 协议的 Socket 无连接通信实现。 UDP(User Datagram Protocol)是无连接、不可靠的传输层协议,在 Winsock 中对应 SOCK_DGRAM。ReactOS 的 UDP 实现在 AFD(afd.sys)的 sendto/recvfrom 路径以及 TCP/IP(tcpip.sys)的 lwIP UDP 实现中。


概述

UDP 通信的关键特性:

  1. 无连接:不需要建立连接,直接发送
  2. 不可靠:不保证数据包到达、不保证顺序、不避免重复
  3. 面向消息 :保留消息边界(一次 sendto 一次 recvfrom
  4. 低延迟:适合 DNS、视频、语音等实时场景

本节内容概览

  • 10.4.0 框架图
  • 10.4.1 UDP 协议概述
  • 10.4.2 UDP socket 创建
  • 10.4.3 sendto 发送数据报
  • 10.4.4 recvfrom 接收数据报
  • 10.4.5 内部数据流
  • 10.4.6 UDP socket 选项
  • 10.4.7 总结与代码索引

学习目标

  • 理解 UDP 通信的工作模型
  • 掌握 sendto/recvfrom 在 AFD 的路径
  • 知道 UDP 数据报如何从 AFD 到 NIC
  • 区分阻塞/非阻塞 UDP 通信

涉及的内核子系统

子系统 头文件/源文件 核心作用
AFD 主 drivers/network/afd/afd/main.c(file:///d:/reactos/drivers/network/afd/afd/main.c) DriverEntry
AFD write write.c(file:///d:/reactos/drivers/network/afd/afd/write.c) AfdSendDatagram
AFD read read.c(file:///d:/reactos/drivers/network/afd/afd/read.c) AfdReceiveDatagram
AFD info info.c(file:///d:/reactos/drivers/network/afd/afd/info.c) socket 信息
TCP/IP drivers/network/tcpip/tcpip/(file:///d:/reactos/drivers/network/tcpip/tcpip/) TCP/IP 协议栈
lwIP UDP drivers/network/tcpip/ip/src/core/udp.c(file:///d:/reactos/drivers/network/tcpip/ip/src/core/udp.c) UDP 实现
Winsock dll/win32/ws2_32/(file:///d:/reactos/dll/win32/ws2_32/) 用户态 Winsock
msafd dll/win32/msafd/(file:///d:/reactos/dll/win32/msafd/) Service Provider

10.4.0 框架图

复制代码
应用 sendto(s, buf, len, 0, addr, addrlen)
              |
              v
+-------------------------------------+
| ws2_32.dll WSPSendTo               |
+-------------------------------------+
              |
              v DeviceIoControl (IOCTL_AFD_SEND_DATAGRAM)
+-------------------------------------+
| AFD AfdSendDatagram                 |  本节主题
| - 构造 TDI_SEND_DATAGRAM 请求        |
+-------------------------------------+
              |
              v IOCTL_TDI_SEND_DATAGRAM
+-------------------------------------+
| TCP/IP tcpip.sys (lwIP udp_send)   |
| - 构造 UDP 头                        |
| - 构造 IP 头                         |
| - ARP 解析目的 MAC                    |
| - NdisSend                           |
+-------------------------------------+
              |
              v
+-------------------------------------+
| NIC Miniport                        |
+-------------------------------------+
              |
              v
         网络硬件

10.4.1 UDP 协议概述

UDP 头(8 字节)

复制代码
 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        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Length               |           Checksum            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       (data)                                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

UDP 应用场景

  • DNS:域名查询(53 端口)
  • DHCP:动态地址分配
  • NTP:时间同步(123 端口)
  • TFTP:简单文件传输
  • 实时音视频:RTP/RTSP
  • 游戏:多人游戏

10.4.2 UDP socket 创建

c 复制代码
// 应用
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

路径

  1. ws2_32.dll::socket()WSPSocket
  2. msafd.dll::WSPSocket 翻译为 IOCTL_AFD_CREATE\Device\Afd
  3. AFD 创建 AFD_ENDPOINT,SocketType = SOCK_DGRAM,Protocol = IPPROTO_UDP
  4. AFD 打开 \Device\Udp 创建设备句柄

AFD 端点初始化

afd/main.c(file:///d:/reactos/drivers/network/afd/afd/main.c):

c 复制代码
NTSTATUS AfdCreate(...)
{
    // ...
    Endpoint->AddressFamily = AF_INET;
    Endpoint->SocketType = SOCK_DGRAM;
    Endpoint->Protocol = IPPROTO_UDP;
    
    // 打开 \Device\Udp
    RtlInitUnicodeString(&DeviceName, L"\\Device\\Udp");
    InitializeObjectAttributes(&ObjAttr, &DeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                              NULL, NULL);
    
    ZwCreateFile(&Endpoint->TdiAddressHandle,
                 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
                 &ObjAttr, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL,
                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                 FILE_OPEN, 0, NULL, 0);
    // ...
}

10.4.3 sendto 发送数据报

应用层

c 复制代码
int sendto(SOCKET s, const char *buf, int len, int flags,
           const struct sockaddr *to, int tolen)
{
    WSABUF wsaBuf = {len, (char*)buf};
    DWORD bytesSent;
    return WSASendTo(s, &wsaBuf, 1, &bytesSent, flags, to, tolen, NULL, NULL);
}

ws2_32.dll::WSASendTo

c 复制代码
int WSAAPI WSASendTo(SOCKET s, LPWSABUF bufs, DWORD bufCount, LPDWORD bytesSent,
                     DWORD flags, const struct sockaddr *to, int tolen,
                     LPWSAOVERLAPPED ovl, LPWSAOVERLAPPED_COMPLETION_ROUTINE cr)
{
    // 翻译为 IOCTL_AFD_SEND_DATAGRAM
    AFD_SEND_DATAGRAM_REQUEST req = {bufs, bufCount, ...};
    AFD_SEND_DATAGRAM_INFO info = {to, tolen, 0, ...};
    
    DWORD bytesReturned;
    BOOL ok = DeviceIoControl((HANDLE)s, IOCTL_AFD_SEND_DATAGRAM,
                              &info, sizeof(info),
                              &req, sizeof(req),
                              &bytesReturned, ovl);
    // ...
}

AFD AfdSendDatagram

write.c(file:///d:/reactos/drivers/network/afd/afd/write.c):

c 复制代码
NTSTATUS AfdSendDatagram(PAFD_ENDPOINT Endpoint, PAFD_SEND_DATAGRAM_INFO SendInfo,
                        PAFD_WSABUF Buf, ULONG BufCount, ULONG *BytesSent)
{
    NTSTATUS Status;
    PIRP Irp;
    PIO_STACK_LOCATION IoStack;
    PTDI_REQUEST_KERNEL_SENDDG DatagramRequest;
    TDI_CONNECTION_INFORMATION ConnInfo;
    PCHAR Buffer;
    UINT BufferLength;
    UINT TotalLength;
    UINT i;
    
    // 1. 构造连接信息(目的地址)
    ConnInfo.UserDataLength = 0;
    ConnInfo.UserData = NULL;
    ConnInfo.OptionsLength = 0;
    ConnInfo.Options = NULL;
    ConnInfo.RemoteAddressLength = SendInfo->TdiOutputBufferSize;
    ConnInfo.RemoteAddress = SendInfo->TdiOutputBuffer;
    
    // 复制目的地址
    RtlCopyMemory(ConnInfo.RemoteAddress, &SendInfo->Address, SendInfo->AddressLength);
    
    // 2. 合并用户缓冲到单一缓冲
    TotalLength = 0;
    for (i = 0; i < BufCount; i++) {
        TotalLength += Buf[i].len;
    }
    
    Buffer = ExAllocatePoolWithTag(NonPagedPool, TotalLength, 'pdaF');
    PCHAR p = Buffer;
    for (i = 0; i < BufCount; i++) {
        RtlCopyMemory(p, Buf[i].buf, Buf[i].len);
        p += Buf[i].len;
    }
    
    // 3. 构造 IRP_MJ_INTERNAL_DEVICE_CONTROL
    DatagramRequest = ExAllocatePoolWithTag(NonPagedPool, sizeof(TDI_REQUEST_KERNEL_SENDDG), 'pdaF');
    DatagramRequest->SendDatagramFlags = 0;
    
    Irp = IoBuildDeviceIoControlRequest(
        IOCTL_TDI_SEND_DATAGRAM,
        IoGetRelatedDeviceObject(Endpoint->TdiAddressHandle),  // Udp 设备
        NULL, 0,  // input
        Buffer, TotalLength,  // output (实际是 input data)
        FALSE, NULL, NULL);
    
    // 4. 设置 IRP
    IoStack = IoGetNextIrpStackLocation(Irp);
    IoStack->Parameters.DeviceIoControl.InputBufferLength = TotalLength;
    IoStack->Parameters.DeviceIoControl.Type3InputBuffer = Buffer;
    IoStack->MinorFunction = TDI_SEND_DATAGRAM;
    
    TdiBuildSendDatagram(Irp, ...);
    
    // 5. 调用 TCP/IP
    Status = IoCallDriver(IoGetRelatedDeviceObject(Endpoint->TdiAddressHandle), Irp);
    
    // 6. 等待
    if (Status == STATUS_PENDING) {
        KeWaitForSingleObject(...);
    }
    
    *BytesSent = TotalLength;
    return Status;
}

10.4.4 recvfrom 接收数据报

应用层

c 复制代码
int recvfrom(SOCKET s, char *buf, int len, int flags,
             struct sockaddr *from, int *fromlen)
{
    WSABUF wsaBuf = {len, buf};
    DWORD bytesRecv;
    DWORD flags_arg = flags;
    return WSARecvFrom(s, &wsaBuf, 1, &bytesRecv, &flags_arg, from, fromlen, NULL, NULL);
}

AFD AfdReceiveDatagram

read.c(file:///d:/reactos/drivers/network/afd/afd/read.c):

c 复制代码
NTSTATUS AfdReceiveDatagram(PAFD_ENDPOINT Endpoint,
                            PAFD_RECV_DATAGRAM_INFO RecvInfo,
                            PAFD_WSABUF Buf, ULONG BufCount,
                            PULONG BytesReceived, PULONG Flags)
{
    PIRP Irp;
    PMDL Mdl;
    
    // 1. 构造 MDL 描述用户缓冲
    Mdl = IoAllocateMdl(Buf[0].buf, Buf[0].len, FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool(Mdl);
    
    // 2. 构造 IRP
    Irp = TdiBuildReceiveDatagram(
        Endpoint->TdiAddressHandle,
        ...,
        Mdl,
        ...,
        RecvInfo->Address, &RecvInfo->AddressLength,
        ...);
    
    // 3. 调用 TCP/IP
    IoCallDriver(IoGetRelatedDeviceObject(Endpoint->TdiAddressHandle), Irp);
    
    // 4. 等待
    if (Irp->IoStatus.Status == STATUS_PENDING) {
        KeWaitForSingleObject(...);
    }
    
    *BytesReceived = Irp->IoStatus.Information;
    return Irp->IoStatus.Status;
}

异步 recvfrom

c 复制代码
// 应用层
WSAOVERLAPPED ovl = {0};
ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
WSARecvFrom(s, &wsaBuf, 1, &bytesRecv, &flags, from, &fromLen, &ovl, NULL);

// 等待
WaitForSingleObject(ovl.hEvent, INFINITE);
GetOverlappedResult(s, &ovl, &bytesRecv, FALSE);

10.4.5 内部数据流

发送:AFD → TCP/IP → NIC

复制代码
WSASendTo
  -> IOCTL_AFD_SEND_DATAGRAM
     -> AfdSendDatagram
        -> IOCTL_TDI_SEND_DATAGRAM
           -> tcpip.sys TdiDispatch
              -> lwIP udp_send
                 -> ip4_output
                    -> NdisSend
                       -> NDIS 库
                          -> Miniport Send
                             -> NIC 发送

接收:NIC → TCP/IP → AFD

复制代码
NIC 接收
  -> Miniport Interrupt
     -> NdisMIndicateReceivePacket
        -> TCP/IP ProtocolReceive
           -> lwIP udp_input
              -> 把数据复制到 AFD 端点的接收队列
                 -> 唤醒等待的 recvfrom 线程
                    -> AfdReceiveDatagram 完成
                       -> WSARecvFrom 返回

lwIP UDP 发送

c 复制代码
// lwIP 内部
err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
{
    // 1. 构造 UDP 头
    struct udp_hdr *udphdr = p->payload;
    udphdr->src = pcb->local_port;
    udphdr->dest = pcb->remote_port;
    udphdr->len = p->tot_len;
    udphdr->chksum = 0;  // 可选校验和
    
    // 2. 调用 IP 发送
    return ip4_output(p, ...);
}

lwIP UDP 接收

c 复制代码
void udp_input(struct pbuf *p, struct netif *inp)
{
    // 1. 解析 UDP 头
    struct udp_hdr *udphdr = p->payload;
    
    // 2. 查找匹配 PCB(基于本地端口)
    for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
        if (pcb->local_port == udphdr->dest) {
            // 3. 把数据排队到 PCB
            pbuf_free(pcb->recv_data);  // 释放旧
            pcb->recv_data = p;
            pcb->recv_flags = ...;
            
            // 4. 通知 AFD
            AfdNotifyUdpReceive(pcb);
        }
    }
}

10.4.6 UDP socket 选项

SO_BROADCAST(广播)

允许发送广播数据报:

c 复制代码
int enable = 1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable));

sendto 的目的地址是 255.255.255.255(或子网广播地址)。

SO_RCVBUF / SO_SNDBUF(缓冲大小)

设置 socket 接收/发送缓冲区大小:

c 复制代码
int size = 65536;
setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));

SO_RCVTIMEO / SO_SNDTIMEO(超时)

设置阻塞 recv/send 的超时:

c 复制代码
struct timeval tv = {5, 0};  // 5 秒
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

IP_MULTICAST_TTL(多播 TTL)

设置多播数据报的 TTL:

c 复制代码
int ttl = 32;
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

10.4.7 总结

关键要点

  1. UDP 无连接:不需要三次握手
  2. 应用 APIsocket(AF_INET, SOCK_DGRAM, 0) + sendto + recvfrom
  3. AFD 路径AfdSendDatagram / AfdReceiveDatagram 通过 TDI_SEND_DATAGRAM
  4. TDI 接口IOCTL_TDI_SEND_DATAGRAM / IOCTL_TDI_RECEIVE_DATAGRAM
  5. lwIP 实现udp_send / udp_input
  6. 数据报保留边界recvfrom 一次调用返回一次发送
  7. socket 选项:SO_BROADCAST、SO_RCVBUF、SO_RCVTIMEO、IP_MULTICAST_TTL

UDP 无连接通信的深度技术分析

UDP(User Datagram Protocol)是互联网基础协议之一,在 ReactOS 网络栈中扮演着重要角色。本节深入分析 UDP 协议在 ReactOS 中的完整实现路径,从应用层 API 到硬件发送的每个环节。

UDP 协议的设计哲学

UDP 的设计遵循"最小化"原则:它只在 IP 协议之上增加了端口号和校验和两个基本功能。这种简洁性带来了几个关键特性:

  1. 无连接:每个数据报独立处理,不需要建立和维护连接状态。
  2. 不可靠:不保证数据报到达、不保证顺序、不重传丢失的数据报。
  3. 低开销:UDP 头只有 8 字节,比 TCP 的 20 字节头更轻量。
  4. 无拥塞控制:不会因网络拥塞而降低发送速率。

这些特性使 UDP 成为实时应用(如视频流、在线游戏、DNS 查询)的理想选择。

ReactOS 中 UDP 的完整数据路径

在 ReactOS 中,UDP 数据报的发送经过以下完整路径:

  1. 应用层 :调用 sendto(s, buf, len, 0, addr, addrlen)

  2. ws2_32.dllsendto 函数将调用转换为 WSASendTo,准备 WSABUF 结构。

  3. msafd.dllWSPSendTo 函数通过 NtDeviceIoControlFile 发送 IOCTL_AFD_SEND_DATAGRAM\Device\Afd

  4. afd.sysAfdSendDatagram 函数处理请求:

    • 验证 socket 状态和参数
    • 构造 TDI 请求结构
    • 合并用户缓冲到单一缓冲区
    • 发送 IOCTL_TDI_SEND_DATAGRAM\Device\Udp
  5. tcpip.sysDispatchTdi 函数处理 TDI 请求:

    • 解析目标地址和端口
    • 查找匹配的 UDP PCB(Protocol Control Block)
    • 调用 lwIP 的 udp_sendto
  6. lwIPudp_send 函数:

    • 分配 pbuf 结构
    • 填充 UDP 头(源端口、目标端口、长度、校验和)
    • 调用 ip4_output 发送 IP 数据报
  7. IP 层ip4_output 函数:

    • 填充 IP 头(源 IP、目标 IP、TTL、协议号 17)
    • 计算 IP 校验和
    • 调用 netif->output(以太网输出函数)
  8. ARP 解析etharp_output 函数:

    • 查找目标 IP 的 MAC 地址
    • 如果未找到,发送 ARP 请求并排队数据报
    • 填充以太网头(源 MAC、目标 MAC、类型 0x0800)
  9. NDIS 发送ethernetif_linkoutput 函数:

    • 分配 NDIS_PACKETNDIS_BUFFER
    • 调用 NdisSend 将包传递给 NDIS 库
  10. Miniport 驱动:NIC 驱动将数据发送到物理介质。

UDP 接收的完整路径

UDP 数据报的接收是发送的逆过程:

  1. NIC 接收:网卡收到帧,触发中断。

  2. Miniport ISR :中断处理程序读取数据,调用 NdisMIndicateReceivePacket

  3. NDIS 分发:NDIS 库将包分发给所有绑定的协议驱动。

  4. tcpip.sys 接收TCPReceive 回调:

    • 分配 pbuf 结构
    • 复制数据到 pbuf
    • 调用 netif->input(lwIP 输入函数)
  5. lwIP 以太网层ethernet_input 函数:

    • 解析以太网头
    • 根据类型字段分发到 IP 层
  6. IP 层ip4_input 函数:

    • 验证 IP 校验和
    • 检查目标 IP
    • 根据协议字段(17)分发到 UDP 层
  7. UDP 层udp_input 函数:

    • 解析 UDP 头
    • 验证 UDP 校验和
    • 查找匹配的 PCB(基于目标端口)
    • 将数据放入 PCB 的接收队列
    • 通知等待的接收者
  8. tcpip.sys 通知:通过 TDI 事件通知 AFD 数据已到达。

  9. afd.sys 完成AfdReceiveDatagram 完成挂起的 IRP:

    • 从 PCB 接收队列取出数据
    • 复制到用户缓冲区
    • 填充源地址信息
    • 完成 IRP
  10. 应用层recvfrom 返回,数据可用。

UDP PCB(Protocol Control Block)管理

lwIP 使用 udp_pcb 结构管理每个 UDP 端点:

c 复制代码
struct udp_pcb {
    struct udp_pcb *next;      // 链表指针
    ip_addr_t local_ip;        // 本地 IP
    ip_addr_t remote_ip;       // 远程 IP
    u16_t local_port;          // 本地端口
    u16_t remote_port;         // 远程端口
    
    // 接收回调
    void (*recv)(void *arg, struct udp_pcb *pcb, 
                 struct pbuf *p, ip_addr_t *addr, u16_t port);
    void *recv_arg;            // 回调参数
    
    // 选项
    u8_t flags;                // 标志(如 UDP_FLAGS_CONNECTED)
    u16_t chksum_len;          // 校验和长度
};

所有 UDP PCB 通过 udp_pcbs 全局链表管理。当收到 UDP 数据报时,udp_input 遍历这个链表,查找匹配的 PCB(基于目标端口和 IP)。

UDP 校验和处理

UDP 校验和是可选的(IPv4 中),覆盖 UDP 头、数据和伪首部。ReactOS 的 lwIP 实现支持校验和计算和验证:

c 复制代码
// 发送时计算校验和
if (pcb->flags & UDP_FLAGS_NOCHK) {
    udphdr->chksum = 0;  // 禁用校验和
} else {
    // 计算伪首部 + UDP 头 + 数据的校验和
    udphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_UDP, 
                                       p->tot_len, src, dest);
}

// 接收时验证校验和
if (udphdr->chksum != 0) {
    if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, src, dest) != 0) {
        // 校验和错误,丢弃数据报
        pbuf_free(p);
        return;
    }
}

UDP 广播和多播

UDP 支持广播和多播两种特殊传输模式:

  1. 广播 :目标 IP 为 255.255.255.255 或子网广播地址。需要设置 SO_BROADCAST socket 选项:

    c 复制代码
    int enable = 1;
    setsockopt(s, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable));
  2. 多播:目标 IP 为 D 类地址(224.0.0.0 - 239.255.255.255)。需要加入多播组:

    c 复制代码
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.1");
    mreq.imr_interface.s_addr = INADDR_ANY;
    setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

ReactOS 的 lwIP 支持广播和多播,通过 IGMP(Internet Group Management Protocol)管理多播组成员。

UDP 的常见问题与解决方案

UDP 的不可靠特性带来几个常见问题:

  1. 数据报丢失:网络拥塞或路由问题导致数据报丢失。解决方案:应用层实现重传机制,或使用 RUDP(Reliable UDP)等协议。

  2. 数据报乱序:网络路径变化导致数据报到达顺序与发送顺序不同。解决方案:应用层添加序列号,重新排序。

  3. 数据报重复:网络重传导致收到重复数据报。解决方案:应用层去重。

  4. 拥塞:UDP 没有拥塞控制,可能导致网络拥塞加剧。解决方案:应用层实现拥塞控制,或使用 DCCP(Datagram Congestion Control Protocol)。

与 Windows UDP 实现的对比

特性 Windows UDP ReactOS UDP
校验和 完整支持 完整支持
广播 完整支持 完整支持
多播 完整支持 基本支持
UDP 封装 支持 不支持
UDP 卸载 支持 不支持
性能优化 零拷贝 标准实现

ReactOS 的 UDP 实现已经能够支持大多数常见的 UDP 应用场景,包括 DNS、DHCP、NTP、TFTP 等。


本章代码索引

文件 内容
afd/main.c(file:///d:/reactos/drivers/network/afd/afd/main.c) DriverEntry
afd/write.c(file:///d:/reactos/drivers/network/afd/afd/write.c) AfdSendDatagram
afd/read.c(file:///d:/reactos/drivers/network/afd/afd/read.c) AfdReceiveDatagram
afd/info.c(file:///d:/reactos/drivers/network/afd/afd/info.c) socket 信息
tcpip/(file:///d:/reactos/drivers/network/tcpip/tcpip/) TCP/IP 协议栈
ip/src/core/udp.c(file:///d:/reactos/drivers/network/tcpip/ip/src/core/udp.c) lwIP UDP
ws2_32/(file:///d:/reactos/dll/win32/ws2_32/) Winsock DLL
msafd/(file:///d:/reactos/dll/win32/msafd/) Service Provider