• 深入浅出TCP之listen


    原文:http://blog.chinaunix.net/uid-29075379-id-3858844.html

    int listen(int fd, int backlog);

    有几个概念需要在开头澄清一下

    TCP socket分两种,监听socket和传输socket两种

    监听socket:负责处理网络上来的连接请求(客户端的syn包到达便是连接请求来了,如果不知道syn包,请参看一下TCP三次握手);

    传输socket:负责在网络上的两个端点之间传输TCP数据。

    未决socket:pending socket,就是某客户端的syn包到达,内核为这个syn包对应的tcp请求生成一个socket,但是此时三次握手并没有完成,这样的socket就是pending socket,是未决连接,没有经过三次握手认证的tcp连接。

    已建立连接的socket:established socket,tcp服务器利用三次握手完成对客户端的简单认证之后,未决socket就变成已连接socket,后续可以用这个socket传输数据。

    内核为每个tcp服务器维护两个socket队列:未决socket队列和已建立连接的socket队列

    29075379_1377067462LOlL.jpg

    图 1

    现在进入主题:)

    在TCP服务器端创建socket完毕,调用listen函数的时候,系统下层发生了以下动作:

    1. 将刚才创建的(fd所标示的)socket转换为此tcp服务器的监听socket,让此socket进入监听请求模式,此socket的tcp状态由CLOSE转至LISTEN.

    2.内核为此监听socket所对应的tcp服务器建立一个未决socket队列和一个已建立连接socket队列

    backlog这个参数用来决定未决socket队列的长度,有个映射关系,0表示长度可以无限大。

     

    现在来串一串整个过程

    监听socket收到某客户端的syn包,第一次握手完成;

    然后内核为此syn请求生成一个pending socket,例如图1中的socket5,标记状态为SYN_RECV,并且将socket5加入相应的pending socket队列,并且服务器发出ack和syn,第二次握手完成。

    后续针对此socket5有两种可能

    1可能

    过会儿客户端响应了服务器的syn(第三个ack到达),第三次握手结束。内核触发accept函数执行,将socket5状态标记为ESTABLISHED,并且将此socket5由pending socket queue移至establishedsocket queue,如图2

    29075379_1377067494nRf1.jpg

    图2

    2可能

    客户端的最后一个ack并未来到,过很久,图1中的socket5超时了,被移除,如图3

    29075379_1377067514BX3v.jpg

    图3

     

    到这儿,listen的作用应该清楚了

    另外针对此listen,有两个极限情况导致的拒绝服务情况需要考虑

    backlog设置过小,pending socket队列已满,此时客户端调用connect发送syn分节给服务器端请求连接,服务端会忽略此syn包,客户端收不到syn的ack,会触发syn超时,这个超时时间比较长,重发syn,导致客户端长时间连接不上。

    backlog设置为0或者过大,只要收到syn包,就会在pending socket队列中增加节点,这个容易导致物理内存耗尽

    Syn flood就是攻击pending socket队列的

    linux内核可以全局设置此pending socket队列大小

    /proc/sys/net/ipv4/tcp_max_syn_backlog

  • 相关阅读:
    数据库练习题
    支付类项目
    crm项目整理
    React 生成二维码
    Charles抓页面配置mac端
    Python之列表生成式、生成器、可迭代对象与迭代器
    01 Django基础
    12 jQuery的ajax
    11 事件委托(事件代理)
    10 jQuery的事件绑定和解绑
  • 原文地址:https://www.cnblogs.com/invisible2/p/8328625.html
Copyright © 2020-2023  润新知