• TCP三次握手,四次挥手异常情况(坑)


    1、三次握手

     

    (文中client,server均是相对而言)

     

      (1)、client第一个syn包丢失,没有收到server的ack,则client进行持续重传syn包。总尝试时间为75秒。参与文献《TCP/IP详解 卷1:协议》p178

      (2)、server收到了client的syn,并发出了syn+ack包,syn+ack包丢失。

        client方面,因为没收server的。将执行情况(1);

        server方面,超时时间内没有收到client的ack包(或者数据包),会持续发送syn+ack包;

      (3)、当Client端收到Server的SYN+ACK应答后,其状态变为ESTABLISHED,并发送ACK包给Server;

        如果此时ACK在网络中丢失,那么Server端该TCP连接的状态为SYN_RECV,并且依次等待3秒、6秒、12秒后重新发送SYN+ACK包,以便Client重新发送ACK包,以便Client重新发送ACK包。
      Server重发SYN+ACK包的次数,可以通过设置/proc/sys/net/ipv4/tcp_synack_retries修改,默认值为5。
      如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。

      如果此时client向server发送数据包,server能正常接收数据。并认为连接已正常。参考:https://blog.csdn.net/zerooffdate/article/details/79359726

      应用层编写socket代码时,三次握手发生在client的connect,所以为了避免长时间(75秒)无响应连接,应设置为非阻塞socket,同时用select检测设置合适的超时时间。

    2、四次挥手

          CLIENT                    SERVER

    (1)、client发的FIN包丢了,对于client,因为没收对应的ACK包,应当一直重传(像普通包一样),直至到达上限次数,直接关闭连接;对于server,它应该无任何感知;

    (2)、server回client的ACK包丢了,对于client,将执行(1),对于server将像丢普通的ack一样,再次收到FIN后,再发一个ACK包;

    (3)、如果client收到ACK后,server直接跑路。client将永远停留在这个状态(半打开状态,就像client关闭了输出一样)。linux有tcp_fin_timeout这个参数,设置一个超时时间 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看,默认60s,可否修改看linux具体版本; windows 注册表有TcpTimedWaitDelay,win10默认值30s;

    (4)、server发的FIN包丢了,对于server,像丢普通的包一样,重传。若此时client早已跑路且与其他人建立的连接,client应会不认识这个FIN包,直接回个RST包给server。

    如若client没跑路,且没收到server的FIN包,如(3)描述;

    (5)、client回复ACK后,按道理来说,可以跑路了,但防止回复的ACK包丢失(丢失后,server因为没收FIN的ACK,所以会再发一个FIN),将等待2MSL(最大报文存活时间)(RFC793定义了MSL为2分钟,Linux设置成了30s)为什么要这有TIME_WAIT?为什么不直接给转成CLOSED状态呢?主要有两个原因:1)TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到Ack,就会触发被动端重发Fin,一来一去正好2个MSL,2)有足够的时间让这个连接不会跟后面的连接混在一起(你要知道,有些自做主张的路由器会缓存IP数据包,如果连接被重用了,那么这些延迟收到的包就有可能会跟新连接混在一起),这期间如若再收到server的FIN,则再回复ACK;

    题外话:

      可以看到时三次握手第二步时,server收到client的SYN包并回复SYN+ACK包后,server会把这条连接放入“半连接队列”。这边有个问题,假设这个client是恶意的,client只发SYN包,收到SYN+ACK后不回复,那在server方面,会一直存有这条“半连接”,client数量达到一定程序,serve就炸了。这就是所谓的SYN FLOOD攻击;那怎么防止这种情况呢?有下面几种方法:(来自RFC 4987

    1. 过滤
    2. 增加积压
    3. 减少SYN-RECEIVED定时
    4. 复用古老的半开通TCP
    5. SYN缓存
    6. SYN Cookie
    7. 混合方法
    8. 防火墙和代理
  • 相关阅读:
    Springboot+mybatis-plus+mysql+clickhouse集成多数据源
    对集合里每个元素是一个对象,按照对象某一个属性值给这个集合排序
    vue的a-tree-select选择父节点回显的是子节点
    Es简单条件查询
    使用Ant Desigen在vue里面实现分页以及表头的模糊查询
    搭建第一个vue项目
    Address localhost:1099 is already in use
    spring的控制反转DI---基于注解实现
    mybatis下的ResultMap配置一对一以及一对多
    mybatis入门
  • 原文地址:https://www.cnblogs.com/quehualin/p/10409607.html
Copyright © 2020-2023  润新知