linux中socket缓冲区大小需通过/proc/sys/net下文件查看:tcp_rmem/wmem含最小、默认、最大值;rmem_max/wmem_max为setsockopt上限(实际分配值翻倍);ss -ti可查运行中socket的rcv_space/snd_space实际容量。

直接查 socket 缓冲区大小:看 /proc/sys/net 下的配置文件
Linux 中 socket 的读写缓冲区大小不是 per-file 的,而是 per-protocol + global 默认值 + 运行时可调参数。你查不到“某个文件”的缓冲区,但能查到 TCP/UDP 协议栈当前生效的缓冲区上下限和默认值。
常见错误是试图用 ls 或 stat 查 socket 缓冲区——它们只管文件元数据,不管内核网络栈配置。
-
cat /proc/sys/net/ipv4/tcp_rmem输出三个数字:最小值、默认值、最大值(单位字节),例如4096 87380 4161536 -
cat /proc/sys/net/ipv4/tcp_wmem同理,对应发送缓冲区 -
cat /proc/sys/net/core/rmem_max和wmem_max是应用层setsockopt能设的最大上限(注意:实际生效值会翻倍) -
cat /proc/sys/net/core/rmem_default和wmem_default是 UDP 和未显式设置的 TCP socket 的初始缓冲区大小
运行中 socket 的实际缓冲区大小:用 ss 或 netstat 查连接状态
ss -i 是目前最可靠的手段,它能显示每个 ESTABLISHED 连接当前的接收/发送队列长度和缓冲区使用情况。
执行 ss -ti(TCP + 详细信息),输出中 rcv_ssthresh、rwnd、rtt 等字段旁的 rcv_space 和 snd_space 就是该 socket 当前内核分配的接收/发送缓冲区容量(单位字节)。
-
ss -ti sport = :80可过滤某端口的连接 -
netstat -tni也能显示类似字段,但部分新内核已弃用,ss更推荐 - 注意:
rcv_space不等于SO_RCVBUF设置值——它受内核自动调优(如 TCP autotuning)影响,可能动态扩大
为什么 setsockopt 设置的值和 getsockopt 读出来的不一致?
这是最容易踩坑的地方:调用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) 后,再用 getsockopt 读回来,值往往比你设的大一倍。
- 内核为每个 socket 缓冲区额外预留一部分用于簿记(bookkeeping),所以实际分配空间 ≈ 设置值 × 2
- 比如你传入
65536,getsockopt返回的通常是131072 - 这个翻倍行为不可关闭,是内核硬编码逻辑,文档明确说明:“The kernel doubles this value (to allow space for bookkeeping)”
- 因此,若要最终得到约 256KB 的可用缓冲空间,应设
131072,而非262144
修改全局默认值需 root 权限,且影响所有新创建的 socket
临时修改(重启失效)直接 echo 写入 /proc/sys/... 文件即可;永久修改需写进 /etc/sysctl.conf 并执行 sysctl -p。
- 例如:让 TCP 接收默认缓冲区从 87380 提升到 524288:
echo 'net.ipv4.tcp_rmem = 4096 524288 4161536' > /proc/sys/net/ipv4/tcp_rmem - 但要注意:
rmem_max必须 ≥ 新的默认值,否则设置会被截断 - UDP 的
rmem_default修改后,对sendto/recvfrom行为影响明显,尤其在高丢包场景下 - 生产环境改前务必验证:改完后跑
ss -ti看新连接是否真的用了新值
ss -ti 的实时输出,而不是查配置文件或代码里写的 setsockopt 值——内核的自适应逻辑会让理论值和现实差得挺远。











