From:
https://www.cnblogs.com/qiumingcheng/p/9492962.html
https://www.jianshu.com/p/8675c12f50ee
backlog参数主要用于底层方法int listen(int sockfd, int backlog)
, 在解释backlog参数之前,我们先了解下tcp在内核的请求过程,其实就是tcp的三次握手:
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指定。
当然也可以通过option方法自定义backlog的大小。
前面已经提到过,内核会根据somaxconn和backlog的较小值设置accept queue的大小,如果想扩大accept queue的大小,必须要同时调整这两个参数。
====================================
TCP建立连接是要进行三次握手,但是否完成三次握手后,服务器就处理(accept)呢?
backlog其实是一个连接队列,在Linux内核2.2之前,backlog大小包括半连接状态和全连接状态两种队列大小。
在Linux内核2.2之后,分离为两个backlog来分别限制半连接(SYN_RCVD状态)队列大小和全连接(ESTABLISHED状态)队列大小。
两个队列在连接过程中所处的位置如下图所示:
先看下man netstat中的说明:
这里有一篇关于这两个队列的分析文章,https://www.cnblogs.com/leezhxing/p/5329786.html,结论是这样,要区分LISTEN状态和其他状态:
在我的机器上做了下验证
$ 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 -apn |grep 8888 tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN 5399/thundering_her
telnet 127.0.0.1 8888
$ ss -l |grep 8888 LISTEN 2 50 127.0.0.1:8888 *:*
Send-Q为2,Recv-Q为listen中设置的值
结论:
两个命令中Send-Q和Recv-Q的含义是不同的,
原文:https://www.cnblogs.com/ylz8401/p/12637864.html