TCP半连接与全连接队列及accept建立连接
日期: 2017-10-28 分类: 个人收藏 324次阅读
我们知道当服务器绑定、监听了指定端口后,内核通常会为每一个LISTEN状态的socket维护两个队列:
- SYN队列(半连接队列):由/proc/sys/net/ipv4/tcp_max_syn_backlog指定,表示处于 SYN_RECV 状态的队列
- ACCEPT队列(全连接队列):由listen()函数的第二个参数 backlog 指定,内核硬限制由 net.core.somaxconn 限制,即实际的值由min(backlog,somaxconn) 来决定。表示已完成连接的队列,等待被 accept系统调用取走。
TCP三次握手如何与accept交互呢?
看下面这张图:
客户端使用connect向服务器发送TCP连接,三次握手就发生了。当1.1步骤 客户端首先发送SYN到达服务端后,内核会把连接信息放到SYN队列中,同时回一个SYN+ACK包给客户端。一段时间后,客户端再次发来ACK包后,内核会把连接从SYN队列中取出,再把这个连接放到ACCEPT队列中。服务器调用accept时,其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字。
还有一张图看下TCP握手过程中建连接的流程和队列:
队满时会发生什么
Q:为什么 有的应用服务器进程,会单独使用一个线程去调用accept来建立服务端和客户端的连接,比如tomcat;而有的则是一个线程做所有的事,即获取连接后还会做I/O等其他操作?
A:首先SYN队列和ACCEPT队列都不是无限大小的,上面已经提到。既然队列长度是有限的,那就有满的时候。比如当上图中步骤1的执行速度大于第2步执行的速度,SYN队列就会不断增大,直到队列满;第2步的执行速度远大于第3步的执行速度,ACCEPT队列同样会满。第1、2步不是程序可控的,第3步是程序的行为。
先看第一种情况:SYN队列满。如果SYN队列满,则会直接丢弃连接请求。
比如syn floods 攻击就是针对半连接队列的,攻击方不停地建连接,但是建连接的时候只做第一步,第二步中攻击方收到server的syn+ack后故意扔掉什么也不做,server需要一个超时时间把这个连接断开,否则大量这样的连接导致server上这个队列满其它正常请求无法进来。
第二种情况:ACCEPT队列满。这种情况貌似比较复杂,我查了学长的博客,发现学长讨论过这个问题。 除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐