TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析

本文详细分析了Linux内核中TCP连接的全连接队列和半连接队列在满载情况下的处理流程。当全连接队列已满,新的连接请求会被服务端接纳但不转为ESTABLISHED状态,而半连接队列满时,服务端会丢弃新的SYN分节。通过抓包实例展示了连接建立过程,并探讨了队列长度设置对连接处理的影响。
摘要由CSDN通过智能技术生成

另外,0端口是系统的保留端口号,若bind时用了0端口,则表示由系统分配一个端口,该端口介于1024和5000之间。


在进行client不断的对server端进行connect的过程中发现下面这个syn_recv状态,而且循环6w次的链接只进行了2W多次就出错了。





于是去查找了下原因:

Linux内核协议栈为一个tcp连接管理使用两个队列,一个是半链接队列(用来保存处于SYN_SENT和SYN_RECV状态的请求),一个是全连接队列(accpetd队列)(用来保存处于established状态,但是应用层没有调用accept取走的请求)。


也就是说,client进行connect之后先进入server的半连接队列,client就直接进入established状态,如果server的全连接队列(accept队列)未满,则将其放入全连接队列(未被应用层进行accpet函数调用取走),然后server也进入established状态。如果全连接队列满了,则server停留在syn_recv状态。

其中全连接队列somaxconn的参数为1表示监听队列的总长度(实际可以完成somaxconn+1个连接的建立)

半连接队列tcp_max_syn_backlog为1(实际可以将tcp_max_syn_backlog+1个syn分节放入其中)

但是在应用层有 int listen(int sockfd, int backlog);。。。然后实际的全连接队列的长度限制是min(backlog, somaxconn);

默认的话半连接队列的长度是/proc/sys/net/ipv4/tcp_max_syn_backlog,默认是1024。如果开启了syncookies,那么基本上没有限制。

全连接队列的长度是/proc/sys/net/core/somaxconn,默认是128,表示最多有129个established链接等待accept。(为什么是129?详见下面的附录1)。


当全连接队列已满且半连接队列未满的情况下:

当客户端发起一个syn分节时,服务端不会丢弃该syn分节,而是直接响应ack和syn,这时客户端响应ack,并成为established状态,而服务端收到ack响应后,试图将该syn分节从半连接队列中移除,并加入全链接队列,然后由于全连接队列已经满了,这时,在默认情况下,服务端啥也不做,而且不会将该连接由SYN_RECV变成ESTABLISHED,服务端仅仅只是创建一个定时器,以固定间隔重传syn和ack到客户端,直到到达系统默认的synack重传阖值,然后服务端将处于半连接队列里面的syn分节丢弃。

当全连接已满且半连接队列也满的情况下:

当客户端发起一个syn分节时,服务端发现半连接队列已经满了,同时该syn分节尚未重传过,服务端直接丢弃该syn分节,然后客户端过了4秒重传syn分节,这个时候服务端发现半连接队列已满同时,该syn分节已经重传过了,服务端收下了该syn分节,并响应客户端syn+ack,客户端收到syn+ack后,响应ack。客户端三次握手已经完成,而服务端收到ack之后,发现全连接队列是满的,这个时候不会将该连接从SYN_RECV转换成ESTABLISHED,服务端创建定时器,定时重传syn+ack, 直到到达系统默认的synack重传阖值,然后服务端将处于半连接队列里面的syn分节丢弃





实际队列中的数量比max的数值大1,标号从0开始,直到max数值也能使用:



实际队列中的数量比max的数值大1,标号从0开始,直到max数值也能使用:


附录1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值