让你明白TCP创建链接的三次握手为何比断开链接的四次挥手少一次?(小白能够看得懂版本)

咱们知道TCP创建链接的时候须要进行三次握手,而结束链接的时候却须要四次挥手。那么为何两次不一致?创建链接的时候为何少一次?java

TCP创建链接的三次握手实际上是四次握手的优化版

若是不进行优化的话,创建链接的过程应该是四次握手(看下图)
在这里插入图片描述
第二次和第三次握手,都是服务器发送数据给客户端,对应上图的服务器端的 第四和第六步骤,可是这两步之间几乎没有耗时的操做,因此就将这两步合并到了一块儿,少了一次握手,变成了三次握手。web

Java启动一个SocketServer

/** * @author KinYang.Lou * @date 2020/4/2 4:05 下午 */
public class SocketServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress(8899));
         accept 会阻塞,一直到有客户链接进来
        Socket accept = serverSocket.accept();
    }
}

serverSocket.accept()会产生阻塞,直到有客户端成功链接进来。
这一步对应上图的服务器端步骤①,直到有客户端链接成功,进行到步骤5-1,代码才会解阻塞,返回一个Socket对象。中间的握手过程,对Java程序来讲是透明的,不可见。服务器

Java启动一个SocketClient

/** * @author KinYang.Lou * @date 2020/4/2 3:02 下午 */
public class SocketClintDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket();
        /// connect 会阻塞,一直到链接创建成功
        socket.connect(new InetSocketAddress("192.168.123.76",8899));
        /// 创建链接成功
        System.out.println("创建链接成功...");
    }
}

socket.connect()也是一个阻塞方法,直到与服务器的链接创建成功。
这一步对应的就是上图的客户端步骤②,直到收到链接成功的通知也就是客户端的步骤8-1,代码才会解阻塞,new出来的socket对象才能够与服务器进行通讯。网络

TCP断开链接的四次挥手为何不能优化成三次?

下面咱们先看一下TCP断开链接的四次挥手过程
在这里插入图片描述socket

断开链接的过程和创建的时候流程基本是同样的,都是互动式,一次消息发送,一次消息回应。
可是为何断开链接的第二次和第三次挥手不能像创建链接的时候,进行合并呢?
这是由于应对到上图的就是服务器端的第三步和第六步之间存在着耗时操做,这个时间不肯定,因此只能分开,先对客户端进行一次收到消息的响应,为了不超过MSL(Maximum Segment Lifetime)的时间。svg

什么是MSL? 每一个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment
Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。
也就是若是我发送一个请求,在MSL时间内,没收到你的确认消息,那么我就认为以前发送的消息发送失败了,就会进行消息重发。优化

为何断开链接的是第三步和第六步之间存在着耗时操做,而创建链接的时候不存在耗时操做?spa

这是由于在断开链接的时候,收到客户端断开请求的时候,服务器可能还有一些数据正在发送给客户端,不能马上关闭发送通道,因此可能须要一段时间才能关闭发送通道。
而创建链接的时候,不存在处理数据的问题,因此也就没有时间消耗,因此能够进行合并,因此就少了一次握手。code