bigywater.tech
Rust · 139

UDP Socket

UDP 与 TCP 的差别不只是「不可靠」。这篇用 Rust 的 UdpSocket 验证:消息边界、截断、大小上限、发给不存在的对端、以及真实的丢包比例。

96.2%
快速发 20000 个数据报时接收端的丢包比例
9216 字节
本机回环地址上能发送的最大 UDP 数据报
3 对 3
发 3 个数据报,收到 3 个独立的数据报(边界保留)

数据报边界

实测 · 本机执行输出
  编译:成功
  运行(退出码 0):
    第 1 次 recv_from:3 字节 "abc",来自发送端地址 == tx 的地址: true
    第 2 次 recv_from:5 字节 "defgh",来自发送端地址 == tx 的地址: true
    第 3 次 recv_from:2 字节 "ij",来自发送端地址 == tx 的地址: true

TCP 的字节流见TCP Listener 与 TcpStream。

缓冲区太小

实测 · 本机执行输出
  编译:成功
  运行(退出码 0):
    用 4 字节缓冲区读一个 10 字节的数据报:recv_from 返回 4,内容 "0123"(剩下的 6 字节丢了)
    下一次 recv_from 得到的是下一个数据报:"NEXT"(不是上一个的剩余部分)

大小上限

实测 · 本机执行输出
  编译:成功
  运行(退出码 0):
    send_to 成功的最大数据报:9216 字节;9217 字节失败:Err((Uncategorized, Some(40)))

这个上限是 macOS 的系统参数(net.inet.udp.maxdgram 一类),换系统不同;没有查该参数。

没有可靠性

实测 · 本机执行输出
  编译:成功
  运行(退出码 0):
    send_to 一个没人监听的端口:Ok(2)(发送方不知道对端不存在)
    connect 到死端口后 send + recv:send 成功;recv 得到 Err((ConnectionRefused, Some(61)))

丢包

实测 · 本机执行输出
  编译:成功
  运行(退出码 0):
    发送 20000 个数据报(共 20000 KB),接收端收到 762 个,丢了 19238 个(96.2%);发送端 send_to 全部返回了成功

丢包比例取决于接收缓冲区大小与发送速度,这次实测是 96.2%,每次不同。

分步演示

UDP
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动。全部使用回环地址
    • 没有验证:真实网络上的乱序与重复、广播与组播、SO_RCVBUF 调大后的丢包率、IPv6 UDP、UDP 校验和、GSO/GRO
    京ICP备2026067502号-1京公网安备11010502063487号