之前已经介绍了TCP协议的三路握手和四次挥手。如下图所示,TCP通信过程包括三个步骤:建立TCP连接通道(三次握手)、数据传输、断开TCP连接通道(四次挥手)。

这里进一步探究TCP三路握手和四次挥手过程中的状态变迁以及数据传输过程。先看TCP状态状态转换图。

1. 建立连接(three-way hand shake)

  • 主动打开(passive open):服务器必须准备好接受外来的连接,通常通过socket、bind和listen完成。
  • 被动打开(active open):客户端通过connect发起主动打开。

插句话,该文介绍的性能分析工具(sar -n TCP,ETCP 1)命令可以对主动打开和被动打开的数目进行统计,在一定程度上可以反应服务器的繁忙程度。

下图给出客户端与服务器的三次握手过程:

  1. 服务器准备好接受外来连接,通常通过socket、bind和listen完成。(服务器:CLOSED->LISTEN)
  2. 客户端通过connect连接服务器,客户端TCP将发送一个SYN包,告诉服务器客户端将在待建立连接发送数据的初始序列号。(客户端:CLOSED->SYN_SENT)
  3. 服务器端必须ACK客户端SYN,同时发送一个SYN,告诉客户端,服务器将在待建立连接发送数据的初始序列号。(服务器:SYN_RCVD)
  4. 客户端必须ACK服务器SYN。(客户端:SYN_SENT->ESTABLISHED)
  5. 服务器接收到客户端ACK。(服务器:SYN_RECV->ESTABLISHED)

下图给出三次握手对应的状态转移图:

2. 建立连接(同时打开simultaneous open)

参考《TCP/IP详解》卷一第18章18.8节。这种情况发生在两端几乎同时发送SYN并且这两个SYN在网络中交错的情形。这种情况可能发生,但是非常罕见。

例如,主机A的应用程序使用本地端口7777,并与主机B的端口8888执行主动打开。主机B的应用程序使用本地端口8888,并与主机A的端口7777执行主动打开。

下图给出同时打开过程:

下图给出同时打开的状态转移图:

说明:从目前个人经验来看,这种场景没有遇到过,但这是完整理解TCP状态转移必须的一部分。但《TCP/IP详解》卷一第18章18.8节中支出,许多伯克利版的TCP实现都不能正确地支持打开。

3. 建立连接失败(1)

考虑场景:客户端尚未接收到服务器ACK+SYN,异常退出(崩溃退出)。这时,当客户端接收到服务器的ACK+SYN时,客户端回复RST(reset)。此时服务器处于SYN_RCVD状态,当接收到客户端RST时,则从SYN_RCVD转移到LISTEN状态。

具体过程:

  1. 服务器准备好接受外来连接,通常通过socket、bind和listen完成。(服务器:CLOSED->LISTEN)
  2. 客户端通过connect连接服务器,客户端TCP将发送一个SYN包,告诉服务器,客户端将在待建立连接发送数据的初始序列号。然后客户端异常退出。(客户端:CLOSED->SYN_SENT,然后突然crash,则退出SYN_SENT)
  3. 服务器端ACK客户端SYN,同时发送一个SYN,告诉客户端,服务器将在待建立连接发送数据的初始序列号。(服务器:SYN_RCVD)
  4. 客户端找不到服务器ACK+SYN对应的SYN_SENT状态的socket,则响应RST。(服务器:SYN_RCVD->LISTEN)

下图给出建立连接失败的状态转移图:

4. 建立连接失败(2)

考虑场景1:服务器的进程异常退出,客户端不知道。那么客户端发送SYN后,服务器端响应RST,则客户端建立连接失败。

考虑场景2:服务器机器关闭,导致服务器IP不可达。那么客户端发送SYN后,超时重发,超过重试次数,最终TIMEOUT,则客户端建立连接失败。

具体过程:

  1. 假设服务器进程退出。(服务器:LISTEN->CLOSED)
  2. 客户端通过connect连接服务器,客户端TCP将发送一个SYN包,告诉服务器,客户将在待建立连接发送数据的初始序列号。(客户端:CLOSED->SYN_SENT)
  3. 服务器端收到客户端SYN,响应RST(服务器:CLOSED)
  4. 客户收到RST。(客户端:SYN_SENT->CLOSED)

下图给出建立连接失败的状态转移图:

5. 断开连接(四次挥手)

  • 主动关闭(active close):某个应用程序首先调用close,发送一个FIN包。
  • 被动关闭(passive close):接收到FIN的对端执行被动关闭。

下图给出客户端与服务器的四次挥手过程:

  1. 某个应用程序首先调用close,该端发送一个FIN包,表示数据发送完毕,该应用程序再无更多数据发送给对端。(例如HTTP服务器发送Reponse数据给client后,再无多余数据发送,则Server可以执行主动关闭)(主动端:ESTABLISHED->FIN_WAIT_1)
  2. 接收到FIN的对端执行被动关闭。首先ACK这个收到的FIN包。该FIN包的接收也作为一个文件结束符(EOF)传递给应用程序(放在已排队等候该应用进程接收的任何其他数据之后),因为FIN包意味着接收端应用进程在相应的连接上再无额外数据可接收。(被动端:ESTABLISHED->CLOSE_WAIT,主动端:FIN_WAIT_1->FIN_WAIT_2)
  3. 一段时间后,接收到这个EOF的应用进程将调用close关闭socket。这导致它的TCP也发送一个FIN包。(被动端:CLOSE_WAIT->LAST_WAIT)  所以CLOSE_WAIT这个状态是让服务器发送还未传送完的数据。
  4. 接收这个最终FIN的执行主动关闭的那一端ACK这个FIN。(被动端:LAST_WAIT->CLOSED,主动端:FIN_WAIT_2->TIME_WAIT(2MSL之后,TIME_WAIT->CLOSED))

下图给出四次挥手的状态转移图:

6. 断开连接(同时关闭simultaneous close)

参考《TCP/IP详解》卷一第18章18.9节。我们在前面讨论了一方(通常但不总是客户方)发送第一个FIN执行主动关闭。双方都执行主动关闭也是可能的,TCP协议也允许这样的同时关闭(simultaneous close)。

下图给出同时关闭过程:

下图给出同时关闭的状态转移图:

7. 断开连接(在FIN_WAIT_1状态中,接收FIN+ACK)

考虑场景:被动关闭端收到FIN包后,直接发送FIN+ACK,则主动关闭方则从FIN_WAIT_1跳过FIN_WAIT_2,直接进入TIME_WAIT。

给出具体流程:

  1. 某个应用程序首先调用close,该端发送一个FIN包,表示数据发送完毕,该应用程序再无更多数据发送给对端。(例如HTTP服务器发送Reponse数据给client后,再无多余数据发送,则Server可以执行主动关闭)(主动端:ESTABLISHED->FIN_WAIT_1)
  2. 接受到FIN的对端执行被动关闭。收到FIN包之后,被动端调用close关闭socket,则FIN+ACK同时发给主动端。(被动端:ESTABLISHED->CLOSE_WAIT->LAST_ACK,主动端:FIN_WAIT_1->TIME_WAIT)
  3. 接收这个最终FIN的执行主动关闭的那一端ACK这个FIN。(被动端:LAST_WAIT->CLOSED,主动端:FIN_WAIT_1->TIME_WAIT(2MSL之后,TIME_WAIT->CLOSED))

下图给出同时关闭的状态转移图:

关于TIME_WAIT需要等2MSL时间才能回到CLOSED状态

TIME_WAIT状态存在的原因有两点:

1.可靠的终止TCP连接

2.保证让迟来的TCP报文段有足够的时间被识别并丢弃

第一点很好解释:如果网络不可靠,那么就无法保证最后客户端发送的ACK报文服务器端一定能够收到,因此处于LAST_ACK状态的服务器可能会因为超时而未收到ACK报文,而重新向客户端发送FIN报文。因此客户端需要停留在TIME_WAIT状态一段时间以处理重复收到的报文段。如果没有这个TIME_WAIT状态,客户端处于CLOSED状态,那么客户端将响应RST(reset),服务器端收到后会将该RST分节解释成一个错误,也就不能实现最后的全双工关闭了(主动方单方的关闭)。所以用TIME_WAIT状态来保证TCP连接的可靠终止。

第二个原因:比如在客户端收到ACK后如果立即关闭,虽然这个端口已经关闭,但如果有一个新的连接被建立起来,使用的IP地址和端口和这个先前到达了CLOSED状态的完全相同,假定原先的连接中还有数据报残存在网络之中,这样新的连接建立以后传输的数据极有可能就是原先的连接的数据报,为了防止这一点,TCP不允许从处于TIME_WAIT状态的socket 建立一个连接,处于TIME_WAIT状态的 socket 在等待了两倍的MSL时间之后,将会转变为CLOSED状态。这里TIME_WAIT状态持续的时间是2MSL(MSL是任何IP数据报能够在因特网中存活的最长时间),足以让这两个方向上的数据包被丢弃(最长是2MSL)。通过实施这个规则,我们就能保证每成功建立一个TCP连接时,来自该连接先前化身的老的重复分组都已经在网络中消逝了。

综上来看:TIME_WAIT存在的两个理由就是

  1. 可靠地实现TCP全双工连接的终止;
  2. 让老的重复分节(数据报)在网络中消逝。

---------------------

本文参考:

1.https://www.cnblogs.com/figo-cui/p/5137993.html

2.https://blog.csdn.net/wenqian1991/article/details/40110703

TCP状态转换图详解相关推荐

  1. 【Unix 网络编程】TCP状态转换图详解

    TCP协议的三路握手和四次挥手.如下图所示,TCP通信过程包括三个步骤:建立TCP连接通道(三次握手).数据传输.断开TCP连接通道(四次挥手). 这里进一步探究TCP三路握手和四次挥手过程中的状态变 ...

  2. 《TCP三次捂手、四次挥手和状态转换详解》

    前言: 本文将讲解TCP三次捂手建立连接,到四次挥手断开连接的过程,并且配合TCP状态转换图解释.解释SYN .seq .ack.FIN的含义和关系.建议读者先理解三捂和四挥后在结合状态转换图看,网络 ...

  3. 4-4:TCP协议之TCP头部格式详解

    文章目录 一:TCP头部格式详解 (1)4位首部长度 (2)序列号和确认应答号 A:可靠性问题 B:32位序号和确认号 (3)窗口大小 (4)标志位 (5)紧急指针 A:带外数据(out_of _ba ...

  4. TCP/IP协议详解、TCP三次握手

    TCP/IP协议详解:TCP/IP协议详解_王佳斌-CSDN博客_tcp/ip协议认识HTTP协议它是互联网协议(Internet Protocol Suite),一个网络通信模型,是互联网的一个基本 ...

  5. 《TCP IP协议 详解》思考总结 · 三

    前言 这一篇文章主要围绕了IP协议,ICMP协议和UDP协议展开,希望可以在这里大概做一个总结,将<TCP/IP协议详解 卷一>书中TCP相关章节前面的内容做一个结束,在下一篇文章专心的去 ...

  6. 计算机网络知识详解之:TCP连接原理详解

    网络知识详解之:TCP连接原理详解 计算机网络相关知识体系详解 网络知识详解之:TCP连接原理详解 网络知识详解之:HTTP协议基础 网络知识详解之:HTTPS通信原理剖析(对称.非对称加密.数字签名 ...

  7. HTTP 状态码详解大全 | HTTP Status Codes

    以下是HTTP 状态码详解大全 | HTTP Status Codes" ,来自维基百科,可以按Ctrl+F快速查找需要的信息 1xx消息 这一类型的状态码,代表请求已被接受,需要继续处理. ...

  8. TCP/IP协议详解卷一:Chapter21 笔记

    TCP/IP协议详解卷一:Chapter21 笔记 Chapter 21 TCP的超时与重传 21.3 往返时间测量 21.5 拥塞举例 21.6 拥塞避免算法 21.7 快速重传与快速恢复算法 21 ...

  9. TCP /IP协议详解【转】

    转自:https://www.jianshu.com/p/0cf648510bce?utm_campaign=maleskine&utm_content=note&utm_medium ...

最新文章

  1. shell脚本执行及配置文件
  2. ECMAScript 6 入门
  3. 你真的弄明白了吗?Java并发之AQS详解
  4. ubuntu下查询SSH状态和安装SSH服务
  5. java中Robot
  6. TRUNCATE和DELETE有以下几点区别
  7. 利用Octopress搭建一个Github博客
  8. shiro springboot 整合
  9. php array_flip() 删除数组重复元素——大彻大悟
  10. 苹果或推出不到两千元的iPhone!安卓手机不淡定了
  11. 双指针:JZ21调整数组顺序使奇数位于偶数前面 Offer 57. 和为s的两个数字
  12. [Photography] 还是DPP好!
  13. 汽车使用总结(七)--侧方停车
  14. 身为码农,为 12306 说两句公道话
  15. 0x00000050蓝屏(0x00000050蓝屏 xp)
  16. js获取内网/局域网ip地址,操作系统,浏览器版本等信息
  17. 06.设计模式之观察者模式
  18. 解决github.io 连接不安全,无法访问
  19. ue4材质节点怎么用_自学ue4材质,一大堆材质节点该如何学?
  20. 嘀嘀和快的部分城市现异常 乘客叫车异常司机接不到单

热门文章

  1. 转移熵matlab,转移熵
  2. php开发斗鱼平台,从斗鱼融资看直播程序的魅力和直播平台的风云变幻
  3. 段地址和偏移地址是什么
  4. 基于 SpringBoot实现文档管理编辑器
  5. python 向量二范数_向量的范数| 使用Python的线性代数
  6. vscode 官网无法下载 解决方法
  7. 阿里云国际版香港服务器测试数据,本次测试使用LemonBench脚本进行。
  8. 陈慧娴《永远是你的朋友》专辑歌词
  9. 科聪控制系统助力铸造行业向“智能”实现“质”的突破!
  10. 前端模块化工具 Browserify