• TCP三次握手和四次挥手


     

    TCP的三次握手和四次挥手流程大家都很清楚,这里只对其中的某些细节进行学习。图1是三次握手与四次挥手的状态图

                       图1 TCP正常连接建立和终止所对应的状态

    问题一:为什么是三次握手,而不是四次握手或者是二次握手
    主要的解释有三点,逐一叙述:
    1.由图1可以看到第二次握手其实是服务器的SYN与ACK一起发送的,如果让服务器分别发送SYN和ACK,这样就是四次握手了,
    不过显然合并发送可以提高效率,所以就是三次握手,实质上是四次握手的优化
    2. 需要三次握手主要是为了保证信道可靠,如果信道可靠,无论什么时候发出消息,对方一定能收的到,三次通信是理论上的最小值,
    所以三次 握手不是TCP本身的要求,而是为了保证信道可靠
    3.为了避免网络中存在延迟的重复分组
    如果采用二次握手,只要服务器端发出ACK,新的连接就建立了。如果存在这样情况,如果之前在建立连接的时候,
    存在客户端的SYN报文由于网络延迟原因没有发送 到服务端,直到之前的连接释放的某个时间才到达服务端,此时服务器收到失效的SYN报文,
    就以为客户端再次发送的一个新的连接请求,如果是二次握手的话,这样 就建 立起连接,但是实质上客户端没有发送ACK,
    因此没有理睬服务器的确认,也不会向服务器发送数据。这样服务器还在苦苦等等客户端发送数据过来,这样服务器就 白白浪费很多资源。

    问题二:三次握手中如果有发包失败怎么办?
    1. 第一个包,即A发送B的SYN包中途被丢,没有到达B
    ---> A会周期性超时重传,直到收到B的确认
    2.第二个包,即B发给A的SYN和ACK中途被丢,没有到达A
    ----> B会周期性超时重传,直到收到A的确认
    3.第三个包,即A发给B的ACK中途被丢,没有到达B
    -->此时A发送完ACK,单方面认为TCP已经建立了,但是B没有认为连接建立了。
    ①:如果此时没有数据发送,B会周期性重传SYN和ACK,直到收到A的ACK为止
    ②:A发送完ACK,单方面认为连接已经建立,假定A有数据发送,B收到A的DATA+ACK。自然就可以建立连接了,也就可以接受DATA了
    ③:B如果有数据发送,数据发送不了,所以也会超时重传SYN和ACK

    问题三:四次挥手中客户端收到服务器的FIN后,处于TIME_WAIT状态,也叫2MSL状态 在这个状态等候2MSL时间有什么用处呢,为什么要等待2MSL时间?

    1:可靠的实现TCP全双工连接的终止
    存在这种情况,如果客户端收到服务器的FIN以后,发送FIN的ACK给服务器,但是服务器没有收到
    这个ACK,服务器会超时发送FIN,如果客户端不等待一段时间,将收不到重发的FIN,就不会重发
    ACK,这样就不能正确的关闭连接,那等待多久比较合适呢?首先服务器有一个超时时间,如果在这个
    超时时间内,收到了客户端的ACK,就可以正常关闭,如果收不到,就会重传FIN,所以这两段时间加起来就是
    服务器的timeout+FIN的传输时间,为了保守起见,采用更加保守的等待时间2MSL,如果2MSL时间内没有收到
    服务器的FIN,那就说明服务器端正确收到ACK了,如果收到了服务器的FIN呢,就客户端就重新发送ACK,这时候
    客户端又会等待2MSL时间。(MSL Maximum Segment Lifetime任何报文段被丢失前在网络内的最长时间)
    2: 允许老的重复字节在网络中消逝。

    关闭一个TCP连接后,过段时间后用相同的地址和IP建立另一个连接,新连接称为老连接的
    化身,因为他们的IP地址和端口号都相同,TCP必须防止来自前一个连接的老的重复分组在该连接终止后再出现。
    因为有可能目前的连接所用的端口和IP在连接断开后立即建立新的连接,新的连接和老的连接端口和IP都一样。如果
    网络中存在旧连接的重复字节,那么TCP协议就认为重复字节是属于新连接的,这样就可能和新的数据包发生混淆。
    为了因对这个问题,TCP不允许处于TIME_WAIT的状态的连接发起
    新的化身。即不允许再使用处于TIME_WAIT阶段的连接的IP 端口号进行连接,既然TIME_WAIT状态的持续时间为2MSL
    就可以保证让某个方向的分组最多存活MSL秒就被丢弃,另一个方向的应答报文最多存活MSL秒就被丢弃,
    通过实施这个规则,我们就能保证每成功建立每个TCP连接时,来自老连接老的重复分组都已经在网络中消逝了

    问题四:为什么关闭连接需要四次挥手?

    四次挥手是TCP的半关闭造成的,所谓的半关闭就是TCP提供了连接的一端在结束他的发送后还能接受另一端数据的能力
    TCP连接时全双工的,所以需要每个方向单独进行关闭,那么能将四次挥手中的第二步和第三步进行合并?这就变成了“三次挥手”了?
    原因是有可能服务端发送ACK的时候还需要发送数据给客户端,所以不能同时发送ACK和FIN,只能先将ACK发送到客户端
    等服务端发送完数据以后,再发送FIN到到客户端

     

  • 相关阅读:
    node-sass 安装失败
    js中复制功能总结
    设置NODE_ENV=test环境变量
    js eslint语法规范错误提示代码
    npm安装node包时怎么显示安装进度
    前端面试题总结三
    5种方式将数字转成千分位
    前端面试题总结二(js原型继承)
    前端面试题总结一(js变量和函数声明提前相关)
    1109 Group Photo (25分)
  • 原文地址:https://www.cnblogs.com/BGPYC/p/7635892.html
Copyright © 2020-2023  润新知