so_rcvbuf/so_sndbuf受rmem_max/wmem_max限制,et模式需循环读至eagain,emfile/enfile需调ulimit或file-max,epipe需检查errno并主动close。

SO_RCVBUF 和 SO_SNDBUF 设置后没生效?
Linux 内核会限制 socket 缓冲区大小的上限,setsockopt 成功不代表最终值就是你设的。内核取的是「min(用户设置值, /proc/sys/net/core/rmem_max)」,写小了没效果,写大了被截断。
- 先检查当前系统上限:
cat /proc/sys/net/core/rmem_max和/proc/sys/net/core/wmem_max - 若需调大,临时改法:
sudo sysctl -w net.core.rmem_max=4194304(4MB);永久生效需写入/etc/sysctl.conf - 调用
setsockopt后,用getsockopt读回确认实际值,别只信返回值为 0 - 注意:TCP 连接建立后,接收缓冲区大小还受
tcp_rmem三元组动态影响,SO_RCVBUF只设初始值
epoll_wait 返回就绪但 read 返回 EAGAIN?
这是边缘触发(ET)模式下的典型误用——没一次性读完所有可用数据,又没重新 epoll_ctl(EPOLL_CTL_MOD),导致后续就绪事件被丢弃。
- ET 模式下,必须循环
read直到返回EAGAIN或EWOULDBLOCK,不能只读一次 - 务必在
read前把errno清零,否则旧错误码可能干扰判断 - 如果用
recv(fd, buf, len, MSG_DONTWAIT)替代read,行为一致,但更明确表达非阻塞意图 - LT 模式虽不强制循环读,但高吞吐场景下仍建议一次读尽,避免频繁唤醒
accept 返回 EMFILE 或 ENFILE 怎么办?
不是程序漏关 fd,而是进程或系统级文件描述符耗尽。前者是 ulimit -n 限制,后者是内核全局 file-max 限制。
本书以培养高级网站建设与管理人才为目标,内容循序渐进,由浅入深,通过大量的实例系统全面地介绍了Linux+PHP+MySQL环境下的网络后台开发技术。本书详尽分析了近30个典型案例。包括计数器、网站流量统计、留言板、论坛系统、聊天室、投票与调查、用户管理、新闻发布系统、广告轮播、购物系统等等,力求让读者通过对案例的学习,轻松掌握PHP和MySQL的编程精要,迅速掌握网络后台开发技巧。 本书适
- 查当前限制:
ulimit -n(进程级),cat /proc/sys/fs/file-max(系统级) - 临时提升进程上限:
ulimit -n 65536,但必须在启动服务前执行,子进程继承 - 检查 fd 泄漏:用
lsof -p <pid></pid>看是否大量socket处于close_wait或未关闭 - 注意
accept返回的 socket 默认继承监听 socket 的CLOEXEC状态,若没显式设FD_CLOEXEC,fork 后可能意外泄露
send 返回 EPIPE 却没触发 SIGPIPE?
默认会触发,但多数服务都调用了 signal(SIGPIPE, SIG_IGN) 屏蔽它——这时 send 直接返回 -1 并置 errno = EPIPE,而不是崩溃。
- 不要依赖 SIGPIPE 终止连接逻辑,一律检查
send返回值和errno -
EPIPE意味着对端已关闭连接(如调用close或进程退出),此时应主动close本端 socket - 若用
send(..., MSG_NOSIGNAL),可临时禁用该次调用的 SIGPIPE,但无法绕过EPIPE错误本身 - 注意:TCP 是全双工,
EPIPE只说明写端失效,读端可能还有残留数据,别急着删 fd
缓冲区大小、事件触发模式、fd 资源、信号处理——这四块看似独立,实则在高并发连接下会连锁反应。比如 SO_RCVBUF 设太小,导致应用层读不及时,socket 接收队列积压,最终触发 netstat 里大量 Recv-Q,进而拖慢 epoll_wait 效率,再加剧 fd 积压……调优得从链路看,不能只盯单点。










