• 朝三慕四


    • 最初两端的TCP进程都处于CLOSE(关闭)状态。
      上图中A主动打开连接,B被动打开连接。
    • B打开连接后处于LISTEN(监听状态),等待客户的连接请求。
    • A向B发送请求报文,SYN=1,ACK=0,选择一个初始序号seq=x。
    • B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为ack= x+1,同时也选择一个初始的序号 seq=y。
    • A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为ack= y+1,序号为 seq=x+1。
    • B 收到 A 的确认后,连接建立。

    TCP的三次握手事情就是这么个事情。(如有错误,还望指正)下面来看看TCP的四次挥手

    以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

    • A 发送连接释放报文,FIN=1。
    • B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
    • 当 B 不再需要连接时,发送连接释放报文,FIN=1。
    • A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。
    • B 收到 A 的确认后释放连接。

     

    四次挥手的原因

    CLOSE-WAIT

    客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

    TIME-WAIT

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

    为什么A在TIME-WAIT状态必须等待2MSL的时间呢?

    这么做有两个理由:

    • 为了保证A发送的最后一个ACK报文段能够到达B。
      A发送的这个ACK报文段有可能丢失,如果 B 没收到 A 发送来的确认报文,那么A就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
    • 防止“已经失效的连接请求报文段”出现在本链接中。
      A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接的时间内所产生的所有报文段都从网络中消失。这样下一个新的连接中就不会出现这种旧的连接请求报文段。

     

    为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

  • 相关阅读:
    对话框中获取Month Calendar的当前日期
    JAVA GUI程序示例
    MFC控件显示值和控件变量值的更新
    JAVA求10到99的随机数
    学习之路二:关于集合和数组内在联系的深入了解
    迭代器学习之三:IEnumerable和IEnumerator的泛型结构
    迭代器学习之四:关于yield的深入了解
    迭代器学习之二:数组的可枚举类型和枚举数的定义以及编译器的foreach工作原理
    学习之路三:关于运用单线程和委托以及事件自定义Timer类
    迭代器学习之一:使用IEnumerable和IEnumerator接口
  • 原文地址:https://www.cnblogs.com/justart/p/11643286.html
Copyright © 2020-2023  润新知