我们知道在 socket 编程中,服务端需要经历 listen → bind → accept 这么几个过程;而客户端需要经历 connect → receive 的过程。其中服务端在 bind 的时候需要指定 backlog 的大小。网上的好多文章,感觉都没有讲清楚这个参数的作用,特在此好好捋一下。方便他人,同时也方便自己。
术语约定:
未完成:半开,处于 SYN_RCVD 状态
已完成:已连接但未 ACCEPT,处于 ESTABLISHED 状态
已完毕:已连接且已 ACCEPT,处于 ESTABLISHED 状态
以下我们这里只讨论未完成和已完成,因为已完毕的都是由应用自己维护。直接上结论:
linux 2.2 之前:
backlog = 未完成 + 已完成
linux 2.2 之后:
backlog = 已完成
需要注意的是,linux 2.2 之后,半连接 syn 队列的长度由 max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog) 所决定;而已完成的队列长度其实是由 min(backlog, somaxconn) 所决定。somaxconn 这个值,在 kernel 2.4.25 之前,都是写死在代码里的,默认为 128。在 kernel 2.4.25 之后,在 /proc/sys/net/core/somaxconn 。
那么问题来了,怎样才能查看进程的 backlog 数量呢?
ss -anp | grep nginx
就可以了。需要注意的是,使用该命令获取到的 Recv-Q/Send-Q 在 LISTEN 状态以及非 LISTEN 状态所表达的含义是不同的:
LISTEN 状态: Recv-Q 表示的是当前已完成队列的大小;Send-Q 表示的则是最大的 listen backlog 数值。
其余状态: Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。
所以上图中显示的是,nginx 的 backlog 为 511,当前已完成队列的大小为 0。那么还有个问题,就是未完成队列在哪里看?很简单:
ss -anp | grep nginx | grep -c SYN_RECV
本文分享自微信公众号 - poslua(poslua)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/4612147/blog/4513334