最直接准确查 socket 发送缓冲区大小的方式是调用 getsockopt() 获取 SO_SNDBUF 值,它返回内核实际分配的字节数(非已用或剩余空间),需在 socket 创建并 bind()/connect() 后调用,且受 wmem_max 限制。

用 getsockopt() 查当前 socket 的发送缓冲区大小
最直接、最准确的方式是调用 getsockopt() 获取运行中 socket 的实际 SO_SNDBUF 值。内核可能对传入的设置值做向上取整(比如你设 64KB,实际返回 131072),也可能因系统限制截断,所以不能只信 set 时的输入值。
关键点:
-
SO_SNDBUF返回的是内核为该 socket 分配的**发送缓冲区字节数**,不是已用或剩余空间 - 必须在 socket 创建后、
connect()或bind()之后调用,否则可能返回默认值(如未显式setsockopt()) - 返回值是“名义大小”,内核内部会额外预留管理开销,真实可用数据空间略小
用 netstat -tulpn 看连接级 Send-Q 实时占用
netstat -tulpn 输出中的 Send-Q 列,显示的是该连接**当前尚未被协议栈发出的字节数**(即发送缓冲区里还卡着多少数据),不是缓冲区上限。
典型场景:
- TCP 连接阻塞(对端接收窗口为 0 或网络卡顿)时,
Send-Q会持续增长 - UDP socket 的
Send-Q永远是 0 —— UDP 不保证送达,发不出去就直接丢弃,不排队 - 这个值是瞬时快照,建议配合
watch -n 0.1 'netstat -tulpn | grep :端口'观察变化趋势
查系统级默认和最大发送缓冲限制
应用层设置 SO_SNDBUF 受限于内核全局参数,超限会被静默截断。必须先确认这些边界:
- 当前默认值:
cat /proc/sys/net/core/wmem_default(单位:字节) - 单 socket 最大允许值:
cat /proc/sys/net/core/wmem_max - UDP 特定最小值:
cat /proc/sys/net/ipv4/udp_wmem_min(即使没 set,内核也会至少分配这么多) - 注意:
wmem_max是硬上限,若你setsockopt()传入 512KB 但wmem_max是 256KB,则最终生效的是 256KB(或其倍数,取决于内核版本)
用 ioctl() 查发送缓冲区当前已用字节数
如果想监控“还剩多少空闲”,得绕过 SO_SNDBUF(它只给容量),改用 ioctl() 调用 SIOCOUTQ:
unsigned long len; ioctl(sockfd, SIOCOUTQ, &len);
这返回的是当前 socket 发送队列中**待发送的字节数**(即已写入但未完成传输的数据量)。对调试背压、判断是否接近满载非常有用。
注意:
- 仅适用于已连接的 socket(TCP 已建立,UDP 已
connect()过) - 对监听 socket(
listen()后未accept())或未连接的 UDP socket,返回 0 - 该值和
netstat的Send-Q逻辑一致,但可编程获取,适合嵌入监控逻辑
SO_SNDBUF 设置值——它只是个目标;真正影响行为的是 SIOCOUTQ 的实时水位,以及 wmem_max 这个看不见的天花板。三者不一致才是常态。


















