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

2023-11-18

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

                                               

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

                                                                                     

上半部分是TCP三路握手过程的状态变迁,下半部分是TCP四次挥手过程的状态变迁。

  1. CLOSED:起始点,在超时或者连接关闭时候进入此状态,这并不是一个真正的状态,而是这个状态图的假想起点和终点。
  2. LISTEN:服务器端等待连接的状态。服务器经过 socket,bind,listen 函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)。
  3. SYN_SENT:第一次握手发生阶段,客户端发起连接。客户端调用 connect,发送 SYN 给服务器端,然后进入 SYN_SENT 状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态。
  4. SYN_RCVD:第二次握手发生阶段,跟 3 对应,这里是服务器端接收到了客户端的 SYN,此时服务器由 LISTEN 进入 SYN_RCVD状态,同时服务器端回应一个 ACK,然后再发送一个 SYN 即 SYN+ACK 给客户端。状态图中还描绘了这样一种情况,当客户端在发送 SYN 的同时也收到服务器端的 SYN请求,即两个同时发起连接请求,那么客户端就会从 SYN_SENT 转换到 SYN_REVD 状态。
  5. ESTABLISHED:第三次握手发生阶段,客户端接收到服务器端的 ACK 包(ACK,SYN)之后,也会发送一个 ACK 确认包,客户端进入 ESTABLISHED 状态,表明客户端这边已经准备好,但TCP 需要两端都准备好才可以进行数据传输。服务器端收到客户端的 ACK 之后会从 SYN_RCVD 状态转移到 ESTABLISHED 状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是 ESTABLISHED 状态,就可以进行后面的数据传输了。所以 ESTABLISHED 也可以说是一个数据传送状态。

上面就是 TCP 三次握手过程的状态变迁。结合第一张三次握手过程图,从报文的角度看状态变迁:SYN_SENT 状态表示已经客户端已经发送了 SYN 报文,SYN_RCVD 状态表示服务器端已经接收到了 SYN 报文。


下面看看TCP四次挥手过程的状态变迁。结合第一张四次挥手过程图来理解。

  1. FIN_WAIT_1:第一次挥手。主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送 FIN 给对方,然后等待对方返回 ACK 。调用 close() 第一次挥手就进入此状态。
  2. CLOSE_WAIT:接收到FIN 之后,被动关闭的一方进入此状态。具体动作是接收到 FIN,同时发送 ACK。之所以叫 CLOSE_WAIT 可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。前面已经说过,TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN 后也需要调用 close 关闭,这个 CLOSE_WAIT 就是处于这个状态,等待发送 FIN,发送了FIN 则进入 LAST_ACK 状态。
  3. FIN_WAIT_2:主动端(这里是客户端)先执行主动关闭发送FIN,然后接收到被动方返回的 ACK 后进入此状态。
  4. LAST_ACK:被动方(服务器端)发起关闭请求,由状态2 进入此状态,具体动作是发送 FIN给对方,同时在接收到ACK 时进入CLOSED状态。
  5. CLOSING:两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1 进入此状态,等待被动方返回ACK。
  6. TIME_WAIT:从状态变迁图会看到,四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入该状态
  • 由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到。
  • 由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方(服务器端)也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序。
  • 由FIN_WAIT_2进入:这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应 ACK。

下面来看看这个看似有点多余的TIME_WAIT状态:从上面进入TIME_WAIT状态的三个状态动作来看(可以直接看状态变迁图)都是主动方最后回应一个ACK(CLOSING实际上前面的那个FIN_WAIT_1状态就已经回应了ACK)。

先考虑这样的一个情况,假如这个最后回应的ACK丢失了,也就是服务器端接收不到这个ACK,那么服务器将继续发送它最终的那个FIN,因此客户端必须维护状态信息(TIME_WAIT)允许它重发最后的那个ACK。如果没有这个TIME_WAIT状态,客户端处于CLOSED状态(开头就说了CLOSED状态实际并不存在,是我们为了方便描述假想的),那么客户端将响应RST,服务器端收到后会将该RST分节解释成一个错误,也就不能实现最后的全双工关闭了(可能是主动方单方的关闭)。所以要实现TCP全双工连接的正常终止(两方都关闭连接),必须处理终止过程中四个分节任何一个分节的丢失情况,那么主动关闭连接的主动端必须维持TIME_WAIT状态,最后一个回应ACK的是主动执行关闭的那端。从变迁图可以看出,如果没有TIME_WAIT状态,我们将没有任何机制来保证最后一个ACK能够正常到达。前面的FIN,ACK正常到达均有相应的状态对应。

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

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

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


参考资料《UNP》《TCP/IP Vol.1》



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Unix 网络编程】TCP状态转换图详解 的相关文章

  • 发起TCP连接关闭后如何接收数据?

    TCP 允许一侧发出 FIN 并让另一侧在结束其一侧的连接之前响应一些数据 我如何使用 NET 来实现这一点TcpClient 看来我必须使用Close发出FIN 但之后我不能再打电话Client Receive since Client被
  • AMQP如何克服直接使用TCP的困难?

    AMQP如何克服直接使用TCP发送消息时的困难 或者更具体地说 在发布 订阅场景中 在 AMQP 中 有一个代理 该代理接收消息 然后完成将消息路由到交换器和队列的困难部分 您还可以设置持久队列 即使客户端断开连接 也可以为客户端保存消息
  • 我应该害怕使用 UDP 进行客户端/服务器广播通话吗?

    我在过去的两天里阅读了每一篇StackOverflow问题和答案 以及googling当然 关于印地TCP and UDP协议 以便决定在我的用户应用程序和 Windows 服务之间的通信方法中应该使用哪一种 从我目前所看到的来看 UDP是
  • 如何强制关闭 TcpListener

    我有一个通过 tcpListener 进行通信的服务 问题是当用户重新启动服务时 抛出 地址已在使用 异常 并且服务在几分钟左右无法启动 有没有办法告诉系统终止旧连接 以便我可以打开一个新连接 我不能只使用随机端口 因为服务无法通知客户端端
  • Linux:如何从特定端口发送TCP数据包?

    如何打开原始套接字以从特定 TCP 端口发送 我希望所有连接始终来自临时端口以下的一系列端口 如果您正在使用raw套接字 然后只需在数据包标头中填写正确的 TCP 源端口即可 相反 如果您使用 TCP 套接字接口 socket connec
  • 当 TCP 序列号到达而不是预期时会发生什么情况?

    我正在编写一个程序 使用 libpcap 捕获数据包并重新组装 TCP 流 我的程序只是监视流量 因此我无法控制数据包的接收和发送 我的程序忽略所有非 TCP IP 流量 我根据 ISN 计算下一个预期序列号 然后计算连续的 SEQ 号 我
  • 谁在 Mac OS X 上监听给定的 TCP 端口?

    在Linux上 我可以使用netstat pntl grep PORT or fuser n tcp PORT找出哪个进程 PID 正在侦听指定的 TCP 端口 如何在 Mac OS X 上获得相同的信息 在 macOS 上Big Sur然
  • 为什么SOCKS5需要通过UDP中继UDP?

    The SOCKS5 https en wikipedia org wiki SOCKS SOCKS5协议 描述为RFC1928 https www rfc editor org rfc rfc1928提供对 UDP 的支持 总而言之 希望
  • Apache HttpClient TCP Keep-Alive(套接字保持活动)

    我的 http 请求需要太多时间才能被服务器处理 大约 5 分钟 由于连接闲置 5 分钟 代理服务器将关闭连接 我正在尝试在 Apache DefaultHttpClient 中使用 TCP Keep Alive 来使连接长时间处于活动状态
  • 使用 IdTCPClient 和 IdTCPServer 发送和接收 TMemoryStream

    我在 XE2 中找到了 Remy Lebeau 的 IdTCP 组件聊天演示 我想玩一下 可以发现 我想使用这些组件发送图片 最好的方法似乎是使用 TMemoryStream 如果我发送字符串 连接工作正常 字符串传输成功 但是当我将其更改
  • 用 C 语言进行非阻塞 udp 套接字编程:我能得到什么?

    我在理解从非阻塞 UDP 套接字返回什么recv recvfrom 时遇到问题 与 TCP 相比更具体一点 如果我错了 请纠正我 阻塞套接字 TCP 或 UDP 在缓冲区中有一些数据之前不会从 recv 返回 这可以是一定数量的字节 TCP
  • TCP 中推送标志和紧急标志之间的区别

    我试图理解带有标志的 TCP 段之间的区别PSH和旗帜URG 我阅读了 RFC 但仍然无法获取它 其中一个在将数据发送到进程之前是否缓冲数据 而另一个则没有 它们是两种截然不同的机制 PSH 和 PUSH 函数 当您发送数据时 您的TCP缓
  • 使用 NestJS 的 TCP 服务器

    是否可以使用 NestJS 创建 TCP 服务器 我有一个仅通过 TCP 进行通信的 GPS 跟踪器 由于 NestJS 可以通过 TCP 在微服务之间进行通信 我认为也许 NestJS 可以用作低级网络应用程序 例如 java netty
  • 如何使用C从http下载文件?

    最近几天我试图弄清楚如何从 URL 下载文件 这是我对套接字的第一个挑战 我用它来了解协议 所以我想在没有 cURL 库的情况下只用 C 语言来完成它 我搜索了很多 现在我可以打印页面的源代码 但我认为这与文件不同 我不必只将接收到的数据从
  • TCL类C10K事件服务器开发进展如何?

    TCL 是一种很好的简单编程语言 但似乎没有得到认可和 或尊重它deserves http antirez com articoli tclmisunderstood html 我 1995 年在大学时就学过它 但很快就忘记了 直到最近才再
  • 确定 TCP Listen() 队列中当前积压的连接数

    有没有办法找出currentLinux 上 TCP 套接字上等待 Accept 的连接尝试次数 我想我可以在每个事件循环上点击 EWOULDBLOCK 之前计算成功的 Accept 数量 但我使用的是隐藏这些细节的高级库 Python Tw
  • Java 客户端到服务器未知来源

    我有一个简单的乒乓球游戏 需要通过网络工作 服务器将创建一个带有球和 2 个球棒位置的游戏 当客户端连接到服务器时 服务器将创建一个名为 PongPlayerThread 的新类 它将处理客户端到服务器的输入和输出流 我的服务器工作100
  • 使用套接字和 AsyncTask 强制关闭

    堆栈的人们大家好 请参阅下面我的班级代码和我的 LogCat 尝试连接时我受到强力关闭 如果有人能帮助我找出原因 我将不胜感激 基本上代码的作用是 从意图中获取 IP 地址 连接到端口 32 的 IP 然后发送一个命令 等待响应并发送另一个
  • 通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时

    我试图通过 SO RCVTIMEO 套接字选项在 Ruby 中设置套接字超时 但它似乎对任何最近的 nix 操作系统都没有影响 使用 Ruby 的 Timeout 模块不是一个选择 因为它需要为每个超时生成和连接线程 这可能会变得昂贵 在需
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成

随机推荐

  • elementui的文件上传功能-.上传文件-带参数-手动

    elementui的文件上传功能 上传文件 带参数 手动
  • JS函数(二)基础 return 返回值

    创建函数 function 函数名 形参变量列表 函数体 return 返回值 return 1 什么是 返回 return语句将终止当前函数并返回当前函数的值 2 为什么要用 我们先来看一组代码
  • matlab矩阵(一)--如何控制矩阵中小数点的位数

    format 设置输出格式对浮点性变量 缺省为format short format并不影响matlab如何计算和存储变量的值 对浮点型变量的计算 即单精度或双精度 按合适的浮点精度进行 而不论变量是如何显示的 对整型变量采用整型数据 整型
  • 汤姆·克鲁斯 - 电影全集

    1 熄灯号 Taps 1981 导演 哈诺德 贝克编剧 Darryl Ponicsan Devery Freeman James Lineberger主演 乔治 C 斯科特 蒂莫西 赫顿 罗尼 考克斯 西恩 潘 汤姆 克鲁斯 伊万 汉德勒
  • HLS图像处理系列——在ZEDBoard搭建DDR图像处理通路

    ZYNQ芯片内包含一个丰富特性的基于双核ARM Cortex A9的处理子系统 Processing System PS 和Xilinx 28nm可编程逻辑 Programmable Logic PL PS除了核心外还包括片上存储器 外部存
  • 端口扫描程序nmap使用手册

    摘要 nmap是一个网络探测和安全扫描程序 系统管理者和个人可以使用这个软件扫描大型的网络 获取那台主机正在运行以及提供什么服务等信息 nmap支持很多扫描技术 例如 UDP TCP connect TCP SYN 半开扫描 ftp代理 b
  • [原创]Discuz!NT1.1高亮代码插件1.5稳定版!

    Discuz NT 1 1高亮代码插件FOR NET2 0 作者 winson 版本 1 5稳定版 支持网站 http bbs szblogs com 功能 为论坛增加高亮代码显示 类似cnblogs的形式 一 1 5版修复的问题 之前发布
  • cgi和fastcgi获取所有环境变量(C语言)

    参考 http blog chinaunix net uid 620765 id 2084386 html 还记得C语言main函数的完整声明吗 int main int argc char argv char envp 这个就是c语言中m
  • c语言解惑 ----读书笔记

    c语言解惑 前言 左值和右值 首地址 没有初始化指针和空指针 指针的初始化 小段存储和大端存储 数组 函数 文件结构 多文件结构 多文件中的函数设计 头文件 前言 面试过程中 发现自己确实对于c和c 实现的原理了解得不够深入 因此借书以解惑
  • IE和FF下查看HTTP头文件信息的插件

    通过这2个插件可以获得服务器返回的页面header信息 对于解析web服务器的工作情况非常有帮助 如查看gzip压缩是否成功及html文件的大小 iehttpheaders下载地址 http www blunck se iehttphead
  • 论文阅读Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks

    论文信息 题目 Sentence Embeddings using Siamese BERT Networks 使用孪生BERT网络结构的句子嵌入 作者 Nils Reimers Iryna Gurevych 论文水平 EMNLP 2019
  • 工程师必知的代码重构指南

    作者 CATE LAWRENCE 译者 冬雨 策划 蔡芳芳 本指南将带你了解进行代码重构的好处 可能遇到的挑战 可以采用的工具和最佳实践 以及重构和技术债务之间的区别 我们都在寻找清理代码 降低复杂性和改进功能的方法 重构就是其中之一 本指
  • mongoDB操作命令大全,掌握最常用的命令

    目录 添加操作 查询操作 复合主键 逻辑操作符匹配 文档游标 文档投影 更新操作 删除操作 添加操作 db 集合 insertOne
  • 面试题二:谈一谈对JavaScript中for in与for of的理解

    for in for in 语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性 包括继承的可枚举属性 在没有深度了解过for in的作用前 我只停留在它能够遍历对象键和数组下标的的层面上 那现在就来探究什么是一个对象中的Symbol
  • 配置centos虚拟机以及虚拟机联网问题

    文章目录 在VMware中创建虚拟机 创建虚拟机 安装centons 7 难点 网络配置 在VMware中创建虚拟机 创建虚拟机 安装centons 7 本文以centos 7 64位为例 各位需要下载centos 7的iso文件 下载地址
  • [网络]公共网络安全漏洞库:CVE/CNCVE

    1 前言 以网络安全行业中最大的 影响范围最广的CVE为例 CVE 的英文全称是 Common Vulnerabilities Exposures 通用漏洞披露 CVE就好像是一个字典表 为广泛认同的信息安全漏洞或者已经暴露出来的弱点给出一
  • 【数据库】redis数据持久化

    目录 数据持久化 一 RDB 1 什么是RDB 2 持久化流程 3 相关配置 案例演示 4 备份和恢复 1 备份 2 恢复 3 优势 4 劣势 二 AOF 1 什么是AOF 2 持久化流程 3 使用AOF 1 开启AOF 2 使用演示 3
  • SDAutoLayout的使用方法

    Cell高度自适应 label文字自适应 1 gt gt 设置cell高度自适应 cell 布局设置好之后调用此方法就可以实现高度自适应 注意 如果用高度自适应则不要再以cell的底边为参照去布局其子view cell setupAutoH
  • IC封装——从基本概念到TSV

    一 IC封装 在之前文章中有大致提过封装 这里展开讲讲 芯片生产流程 沧海一升的博客 CSDN博客每个半导体产品的制造都需要数百个工艺 泛林集团将整个制造过程分为八个步骤 晶圆加工 氧化 光刻 刻蚀 薄膜沉积 互连 测试 封装 芯片生产流程
  • 【Unix 网络编程】TCP状态转换图详解

    在前面 已经介绍了TCP协议的三路握手和四次挥手 如下图所示 TCP通信过程包括三个步骤 建立TCP连接通道 三次握手 数据传输 断开TCP连接通道 四次挥手 这里进一步探究TCP三路握手和四次挥手过程中的状态变迁以及数据传输过程 先看TC