linux查看全连接队列大小,linux tcp socket 请求队列大小参数 backlog 简介

本文详细介绍了Linux系统中TCP连接队列的管理,特别是backlog参数在listen函数中的作用。backlog是连接队列的大小,它受到系统参数somaxconn的限制。backlog不仅包括半连接状态的SYN队列,也包含全连接状态的accept队列。当accept队列满时,服务器将拒绝新的连接请求。在Linux 2.2之后,SYN队列和accept队列被分开管理。可以通过调整/proc/sys/net/ipv4/tcp_max_syn_backlog和/proc/sys/net/core/somaxconn来控制队列大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

底层

backlog参数主要用于底层方法int listen(int sockfd, int backlog), 在解释backlog参数之前,我们先了解下tcp在内核的请求过程,其实就是tcp的三次握手:

3ce7aa4b045388dc80092141ef3e2f25.png

1、client发送SYN到server,将状态修改为SYN_SEND,如果server收到请求,则将状态修改为SYN_RCVD,并把该请求放到syns queue队列中。

2、server回复SYN+ACK给client,如果client收到请求,则将状态修改为ESTABLISHED,并发送ACK给server。

3、server收到ACK,将状态修改为ESTABLISHED,并把该请求从syns queue中放到accept queue。

在linux系统内核中维护了两个队列:syns queue和accept queue

syns queue

用于保存半连接状态的请求,其大小通过/proc/sys/net/ipv4/tcp_max_syn_backlog指定,一般默认值是512,不过这个设置有效的前提是系统的syncookies功能被禁用。互联网常见的TCP SYN FLOOD恶意DOS攻击方式就是建立大量的半连接状态的请求,然后丢弃,导致syns queue不能保存其它正常的请求。

accept queue

用于保存全连接状态的请求,其大小通过/proc/sys/net/core/somaxconn指定,在使用listen函数时,内核会根据传入的backlog参数与系统参数somaxconn,取二者的较小值。

如果accpet queue队列满了,server将发送一个ECONNREFUSED错误信息Connection refused到client。

应用层

在netty实现中,backlog默认通过NetUtil.SOMAXCONN指定。

8246c99541156d0d44608728d8df1708.png

当然也可以通过option方法自定义backlog的大小。

85e0176eb1759fa72ba17a7d3f19b61c.png

backlog设置注意点

前面已经提到过,内核会根据somaxconn和backlog的较小值设置accept queue的大小,如果想扩大accept queue的大小,必须要同时调整这两个参数。

====================================

backlog参数的含义

TCP建立连接是要进行三次握手,但是否完成三次握手后,服务器就处理(accept)呢?

backlog其实是一个连接队列,在Linux内核2.2之前,backlog大小包括半连接状态和全连接状态两种队列大小。

半连接状态为:服务器处于Listen状态时收到客户端SYN报文时放入半连接队列中,即SYN queue(服务器端口状态为:SYN_RCVD)。

全连接状态为:TCP的连接状态从服务器(SYN+ACK)响应客户端后,到客户端的ACK报文到达服务器之前,则一直保留在半连接状态中;当服务器接收到客户端的ACK报文后,该条目将从半连接队列搬到全连接队列尾部,即 accept queue (服务器端口状态为:ESTABLISHED)。

在Linux内核2.2之后,分离为两个backlog来分别限制半连接(SYN_RCVD状态)队列大小和全连接(ESTABLISHED状态)队列大小。

SYN queue 队列长度由 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定,默认为2048。

Accept queue 队列长度由 /proc/sys/net/core/somaxconn 和使用listen函数时传入的参数,二者取最小值。默认为128。在Linux内核2.4.25之前,是写死在代码常量 SOMAXCONN ,在Linux内核2.4.25之后,在配置文件 /proc/sys/net/core/somaxconn 中直接修改,或者在 /etc/sysctl.conf 中配置 net.core.somaxconn = 128 。

两个队列在连接过程中所处的位置如下图所示:

995da15ad5a555561e172baccfd1044d.png

tcp_backlog.png

如何查看监听状态

206a4fcc5dcd7a9986234a430baa057e.png

Recv-Q & Send-Q

先看下man netstat中的说明:

Recv-Q:The count of bytes not copied by the user program connected to this socket.

Send-Q:The count of bytes not acknowledged by the remote host.

这里有一篇关于这两个队列的分析文章,https://www.cnblogs.com/leezhxing/p/5329786.html,结论是这样,要区分LISTEN状态和其他状态:

LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept();Send-Q 表示的则是最大的 listen backlog 数值,这就就是上面提到的 min(backlog, somaxconn) 的值。

其余状态: 非 LISTEN 状态之前理解的没有问题。Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。

在我的机器上做了下验证

操作系统

$ uname -a

Linux ubuntu 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

在8888这个端口启动一个监听程序, 程序中不accept

netstat命令查看

$ netstat -apn |grep 8888

tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN 5399/thundering_her

打开两个telnet连接

telnet 127.0.0.1 8888

ss命令查看

$ ss -l |grep 8888

LISTEN 2 50 127.0.0.1:8888 *:*

Send-Q为2,Recv-Q为listen中设置的值

结论:

两个命令中Send-Q和Recv-Q的含义是不同的,

netstat中应该是man里面说明的含义

ss中才是上面文章中的结论:

Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值;

Send-Q 表示min(backlog, somaxconn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值