美文网首页TCP/IP网络编程TCP/IP协议JAVA TCP/IP Socket详解
BAT面试高频题目:TCP半连接队列和全连接队列

BAT面试高频题目:TCP半连接队列和全连接队列

作者: 名猿 | 来源:发表于2019-09-28 21:42 被阅读0次

    TCP半连接队列和全连接队列

    1 简单的TCP建连流程

    先来张图,如下:

    (1)client端使用connect()向server端发起连接请求(发送syn包),此时client端的TCP的状态为SYN_SENT

    (2)server端在收到SYN包后,将TCP相关信息放到syn queue(半连接队列)中,同时向client发送syn+ack。server端TCP的状态为

    SYN_RCVD。

    (3)client端收到server端的syn+ack后,向server端发送ack,此时client端的TCP的状态为ESTABLISHED。Server端收到ack确认后,从syn

    queue里将TCP信息取出,并放到accept quee(全连接队列)中,此时server端的TCP的状态为ESTABLISHED。

    经过以上三个过程,client端和server端建立了连接,即所有三次握手的过程。

    2半连接状态与全连接状态

    通过上图和上述流程中可以看到TCP有两个队列:半连接队列(SYN queue)与全连接队列(accept queue),分别用来存放半连接状态和全连接状态信息。

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

    全连接状态:指TCP状态为的状态ESTABLISHED。TCP的连接状态从服务器(SYN+ACK)响应客户端后,到客户端的ACK报文到达服务器之前,

    则一直保留在半连接状态中;当服务器接收到客户端的ACK报文后,该条目将从半连接队列移到全连接队列尾部,即 accept queue。

    从linux内核2.2开始,系统分离成两个backlog分别限制半连接(SYN_RCVD状态)队列大小和全连接(ESTABLISHED状态)队列大小。

    3 半连接队列(SYN queue)

    SYN queue 队列长度由 net.ipv4.tcp_max_syn_backlog 指定,默认值是根据内存大小而定,如果系统内存超过128MB,默认值为1024,低于

    128MB时为128。

    当 SYN queue满了,系统还在不断的收到 SYN 包时,系统怎么处理的?系统会根据内核参数net.ipv4.tcp_syncookies的值来处理请求。

    tcp_syncookies是用来防止SYN flood攻击,其原理是在半连接队列满时,SYN cookies并不丢弃SYN请求,而是将源目的IP、源目的端口号、接

    收到的client端初始序列号以及其他一些安全数值等信息进行hash运算,并加密后得到server端的初始序列号,称之为cookie。server端在发送初

    始序列号为cookie的SYN+ACK包后,会将分配的连接请求块释放。如果接收到client端的ACK包,server端将client端的ACK序列号减1得到的值,

    与上述要素hash运算得到的值比较,如果相等,直接完成三次握手,构建新的连接。SYN cookies机制的核心就是避免攻击造成的大量构造无用的

    连接请求块,导致内存耗尽,而无法处理正常的连接请求。

    当syn queue满了,在Server端没有开启syncookies的时候,即syncookies=0,server端会丢弃新来的SYN包,而client端在多次重发SYN包得不

    到响应而返回connection time out错误。但是,当Server端开启了syncookies,即syncookies=1,那么SYN queue就在逻辑上的没有最大值了,

    而是忽略内核参数net.ipv4.tcp_max_syn_backlog设置的值。Client端在多次重发SYN包得不到响应而返回connection time out错误

    注意,即使开启该机制并不意味着所有的连接都是用SYN cookies机制来完成连接的建立,只有在SYN queue已满的情况下才会触发SYN cookies

    机制。由于SYN cookies机制严重违背TCP协议,不允许使用TCP扩展,可能对某些服务造成严重的性能影响(如SMTP转发),对于防御SYN

    flood攻击的确有效。对于没有收到攻击的高负载服务器,不要开启此选项,可以通过修改tcp_max_syn_backlog、tcp_synack_retries和

    tcp_abort_on_overflow系统参数来调节。

    查看系统最大半队列大小

    可以使用下面两种方面查看系统最大半队列大小:#sysctl -a|grep max_synnet.ipv4.tcp_max_syn_backlog = 65536

    #cat /proc/sys/net/ipv4/tcp_max_syn_backlog65536

    查看系统当前半队列大小

    # ss -s

    Total: 18008 (kernel 103906)

    TCP: 23359 (estab 188, closed 23104, orphaned 64, synrecv 0, timewait 10000/0), ports 0

    Transport Total IP IPv6* 103906 - -

    RAW 0 0 0

    UDP 1 1 0

    TCP 255

    INET 256

    FRAG 0如何查看是否有溢出的SYN# netstat -s|grep LISTEN

    1007759 SYNs to LISTEN sockets ignored

    4 全连接队列(Accept queue)

    在第三次握手时,当server端接收到ACK 报之后, 会进入一个叫accept queue,Accept queue 队列长度由 net.core.somaxconn 和应用程序使

    用listen函数时传入的参数,二者取最小值。默认为128,表示最多有 129 的 ESTABLISHED的连接等待 accept()。

    当Accept queue满了以后,即使client端继续向server端发送ACK的包,也会不被响应,此时ListenOverflows+1,系统会根据net.ipv4.

    tcp_abort_on_overflow参数的值来决定如何返回。值为0表示直接丢弃该ACK,但不会从连接信息从SYN queue队列中移除。当系统丢弃了最后

    阶段的 ACK,系统会根据参数net.ipv4.tcp_synack_retries的设置重新向client端发送 SYN+ACK 包。而client端在收到多个 SYN+ACK 包,会认

    为之前的ACK丢包了,于是client端又重新向server端发送ACK包。当在 accept queue有空闲的时候最终完成连接。如果accept queue始终满

    员,则最终client将收到RST包。

    如果net.ipv4.tcp_abort_on_overflow参数值为1表示server端发送RST通知client;与此同时,client则会分别返回read timeout 或者

    connection reset by peer。

    249 6

    250 6

    0 0

    可以通过ss/netstat查看全队列的长度:

    #ss –ln

    Recv-Q Send-Q Local Address:Port

    0 128 *:80

    说明:

    Peer Address:Port

    *:*

    TCP状态为LISTEN状态的Send-Q字段的值为全队列最大长度,即min(backlog, somaxconn) 的值,Recv-Q字段的值,表示当前等待服务端调用

    accept 完成三次握手的 listen backlog 数值,即当前全队列已用长度。

    非 LISTEN 状态中Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。查看Accept queue 是否有溢出

    # netstat -s | grep TCPBacklogDrop

    TCPBacklogDrop: 8924

    相关文章

      网友评论

        本文标题:BAT面试高频题目:TCP半连接队列和全连接队列

        本文链接:https://www.haomeiwen.com/subject/cdxxpctx.html