zoukankan      html  css  js  c++  java
  • TCP的三次握手和四次挥手

    TCP的三次握手

    • TCP 建立连接的过程叫做握手。
    • 握手需要在客户和服务器之间交换三个 TCP 报文段。称之为三报文握手。
    • 采用三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。

    过程:

    1. A 的 TCP 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。
    2. B 的 TCP 收到连接请求报文段后,如同意,则发回确认。B 在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号ack = x+1,自己选择的序号 seq = y。
    3. A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1。A 的 TCP 通知上层应用进程,连接已经建立。
    4. B 的 TCP 收到主机 A 的确认后,也通知其上层应用进程:TCP 连接已经建立。

    为什么是三次握手而不是两次

    • 为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。

    解释原因:如果在发送过程中的话,假如是两次:当A给B发送一个连接请求,因为网络的原因该请求没有按时到达,A就会重新发送一次请求,这次请求正常到,然后B就会给A一个确认请求,此时就可以传送数据了。但是当A第一次发送的数据又来到了(A以为这个包已经丢失了),那么B就会再次向A发送一个确认,此时的A就不知道这个确认的意义了,而B就会在一直等待着A给他发送信息(如果这样的次数很多就会导致资源浪费)。所以说不能是两次。

    TCP的四次挥手

    也可以看成两次握手(A的释放和B的释放)

    过程:

    1. 现在 A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的 FIN = 1,其序号seq = u,等待 B 的确认。
    2. B 发出确认,确认号 ack = u + 1,而这个报文段自己的序号 seq = v。TCP 服务器进程通知高层应用进程。从 A 到 B 这个方向的连接就释放了,TCP 连接,处于半关闭状态。B 若发送数据,A 仍要接收。
    3. 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。
    4. A 收到连接释放报文段后,必须发出确认。
    5. 在确认报文段中 ACK = 1,确认号 ack = w + 1,自己的序号 seq = u + 1。

    四次挥手的原因

    为什么是四次挥手而不是三次:
     
    在三次握手的过程中,SYN和ACK是一起发送的但是在四次挥手的时候FIN和ACK却不是一起发送的而是分开发送的,为什么呢???
    那是因为啊,TCP连接是全双工的也就是说接收到FIN只是说没有数据再发过来但是还是可以发送数据的,也就是接受到一个FIN只是关闭了一个方向的数据传输,另一个方向还可以继续发送数据。在四次挥手的时候也是这样前两次挥手只是确认关闭了一个方向的数据,加上后面两次挥手才真正的关闭了整个全双工连接。

          当socket在ESTABISHED状态时,他想主动关闭连接于是向对方发送FIN请求,发送完FIN请求后它处于FIN_WAIT_1状态,当对方确认ACK报文后则处于FIN_WAIT_2状态。FIN_WAIT_2表示半连接,也就是有一方要求关闭连接,另一方收到请求但是告诉她我还有一些数据要发送稍后会关闭。TIME_WAIT状态表示收到对方的FIN并发送出ACK.如果三次挥手可能在关闭后还有一个方向没有关。

    1.前俩次挥手:结束一个方向上的链接

    2.后俩次挥手:结束另外一个方向上的链接

    TIME_WAIT

    客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

    • 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。

    • 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文

    通俗的来讲解三次握手和四次挥手

    通俗的来说就是:

    三次握手: 通俗的来讲就是 A和B打电话

    第一次握手 : 你好, 我是A, 你能听到我说话吗

    第二次握手 : 听到了, 我是B, 你能听到我说话吗

    第三次握手 : 听到了, 我们可以开始聊天了

     

    三次握手其实就是为了检测双方的发送和接收能力是否正常, 你说呢?

    四次挥手

    第一次挥手 : A告诉B, 我没数据发了, 准备关闭连接了, 你要发送数据吗

    第二次挥手 : B发送最后的数据

    第三次挥手 : B告诉A, 我也要关闭连接了

    第四次挥手 : A告诉B你可以关闭了, 我这边也关闭了

     

    也可以这样:

    A:“喂,我不说了 (FIN)。”A->FIN_WAIT1

    B:“我知道了(ACK)。等下,上一句还没说完。Balabala…..(传输数据)”B->CLOSE_WAIT | A->FIN_WAIT2

    B:”好了,说完了,我也不说了(FIN)。”B->LAST_ACK

    A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED

    A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED

    TCP状态转化图

    先看 粗实线箭头,

    再看粗虚线箭头

    推荐博文:

    https://github.com/jawil/blog/issues/14

    https://www.cnblogs.com/xiaokang01/p/9057004.html#_label0_3

  • 相关阅读:
    tmp
    GO语言中使用OpenCV
    The OpenCV Coding Style Guide
    下载tree命令的源代码
    convention over configuration 约定优于配置 按约定编程 约定大于配置 PEP 20 -- The Zen of Python
    tmp
    起步依赖
    Spring Boot Dubbo Dubbok spring cloud
    pug.compile() will compile the Pug source code into a JavaScript function that takes a data object (called “locals”) as an argument.
    request /a?b= /a/?b=
  • 原文地址:https://www.cnblogs.com/xiaokang01/p/10032377.html
Copyright © 2011-2022 走看看