TCP系列07—连接管理—6、TCP连接管理的状态机
一、TCP状态机整体状态转换图(截取自第二版TCPIP详解)

二、TCP连接建立和终止过程中状态迁移总结
下面我们总结一下前面介绍过的连接建立方式和终止过程中client端和server端的状态切换
1、三次握手
client:CLOSED -> SYN_SENT -> ESTABLISHED
server:CLOSED -> LISTEN -> SYN_RCVD ->ESTABLISHED
2、四次挥手
client:ESTABISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
server:ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
3、TCP同开
client:CLOSED->SYN_SENT->SYN_RCVD->ESTABLISHED
server:CLOSED->SYN_SENT->SYN_RCVD->ESTABLISHED
4、TCP同关
client:ESTABLISHED->FIN_WAIT_1->CLOSING->TIME_WAIT->CLOSED
server:ESTABLISHED->FIN_WAIT_1->CLOSING->TIME_WAIT->CLOSED
5、三次挥手
client:ESTABISHED->FIN_WAIT_1->TIME_WAIT->CLOSED
server:ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
注意此处server侧内部虽然经历了ESTABLISHED->CLOSE_WAIT的状态转换,但是实际在由ESTABLISHED状态转换到CLOSE_WAIT状态的过程中并没有发送ACK包,ACK实际是随着CLOSE_WAIT->LAST_ACK状态切换过程中的FIN包一起发送的。可以观察前面文章wireshark抓包示例图。
三、一些状态说明
1、TIME_WAIT状态
TIME_WAIT状态也叫做2MSL等待状态。MSL(Maximum Segment Lifetime)中文可以译为报文最大生存时间。TIME_WAIT则是指Active Opener在连接结束前要等待2MSL的时间,有时这个状态也叫做timed wait。RFC793指定MSL时长为2分钟,但是在实现上可能会使用其他值。实际上在active close的时候,部分场景下linux会把FIN_WAIT_2作为TIME_WAIT的一个子状态。linux中net.ipv4.tcp_fin_timeout可以设置FIN_WAIT_2定时器的值。
TIME_WAIT主要由两个作用一个是给active closer重新发送ACK报文的机会。当active closer发送完最后一个ACK后,继续保留2MSL时间,这样如果passive closer没有收到最后一个ACK而重发FIN的情况下,可以让active closer机会重新发送ACK报文。另外一个作用则是同一个四元组(源ip、源端口、目的IP、目的端口)标识的连接一般只有在TIME_WAIT结束后才能重新建立。但是有两种例外情况,一种是新连接SYN中的seq系列号比之前相同连接实例相同方向的最大系列号还要大(RFC1122),或者通过时间戳的扩展可以区分出这同一个连接的不同实例(RFC6191)。
如果一台主机在TIME_WAIT状态下崩溃并且快速重启,然后以之前的四元组建立一个相同的连接,如果这个过程时间够短,那么有可能之前连接实例的数据包错误的被接收并当作有效的数据包。为了保护这种场景,RFC793要求一个主机在重启后需要等待MSL时间后在创建新的TCP连接,这个就是平静时间(quiet time)。因为大多数主机重启需要的时间可能都比MSL长,因此主机在实现上可能并不会真的等待MSL时间在建立TCP连接。另外再次说一下应用层如果对数据完整性要求比较高,需要自己添加校验。
2、FIN_WAIT_2状态
在实现上,如果Active Closer的应用程序是彻底关闭TCP连接(调用close接口),而不是指示半关TCP连接(shutdown)接口,那么这个endpoint并不会一直停留在FIN_WAIT_2状态,而是会设置一个定时器,一旦定时器超时,这个连接还没有收到数据包,那么这个endpoint会直接进入CLOSED状态。这个定时器的值同样受net.ipv4.tcp_fin_timeout控制。
补充说明:
1、从LISTEN状态切换到SYN_SENT状态,协议是支持的,但是在linux实现上是不支持的
2、为了支持TFO,目前TCP内部实际上是12种TCP状态,新添加了一个NEW_SYN_RCVD用于传统的tcp连接,普通连接在收到三次握手最后的ACK的时候,会从NEW_SYN_RCVD切换到SYN_RCVD然后在切换到ESTABLISHED。
https://patchwork.ozlabs.org/patch/449704/
3、用于支持容器间TCP迁移的tcp repair模式,TCP在不发送数据包的情况下也可以直接由CLOSED切换到ESTABLISHED,但是这个属于实现层面的状态切换。
https://lwn.net/Articles/495304/
https://www.youtube.com/watch?v=IkH7p2jmxok
4、Linux下TIME-WAIT处理参考tcp_timewait_state_process,其中RFC1122和RFC6191给出的两种在TIME-WAIT下建立同一个连接的新实例的场景,linux都已实现。另外要说明一下的是当使用close系统调用关闭TCP连接的时候,最后的FIN-WAIT2在linux内部实际是作为TIMEWAIT的一个子状态存在的。
TCP系列07—连接管理—6、TCP连接管理的状态机的更多相关文章
- TCP系列11—重传—1、TCP重传概述
在最开始介绍TCP的时候,我们就介绍了TCP的三个特点,分别是面向连接.可靠.字节流式.前面内容我们已经介绍过了TCP的连接管理,接下来的这部分内容将会介绍与TCP可靠性强关联的TCP重传. 很多网络 ...
- TCP系列08—连接管理—7、TCP 常见选项(option)
一.TCP选项概述 在前面介绍TCP头的时候,我们说过tcp基本头下面可以带有tcp选项,其中有些选项只能在连接过程中随着SYN包发送,有些可以延后.下表汇总了一些tcp选项 其中我标记为红色的部分是 ...
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
一.TCP连接的ISN 之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...
- TCP系列02—连接管理—1、三次握手与四次挥手
一.TCP连接管理概述 正如我们在之前所说TCP是一个面向连接的通信协议,因此在进行数据传输前一般需要先建立连接(TFO除外),因此我们首先来介绍TCP的连接管理. 通常一次完整的TCP数据传输一般包 ...
- TCP系列03—连接管理—2、TCP连接的同时打开和同时关闭
在前面的内容中我们介绍了TCP连接管理中最常见的三次握手方式和四次挥手的方式.但是有可能A和B两端同时执行主动打开并连接对方或者同时执行主动关闭连接(尽管发生这种情况的可能性比较低低),这个时候的流程 ...
- TCP系列04—连接管理—3、TCP连接的半打开和半关闭
在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...
- SQL Server 连接问题-TCP/IP
原文:SQL Server 连接问题-TCP/IP 出自:http://blogs.msdn.com/b/apgcdsd/archive/2012/02/24/ms-sql-server-tcp-ip ...
- 小tips:TCP的三次握手、长连接、 短连接、 SPDY 协议
当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需 ...
- 异数OS TCP协议栈测试(三)--长连接篇
异数OS TCP协议栈测试(三)--长连接篇 本文来自异数OS社区 github: 异数OS-织梦师(消息中间件)群: 476260389 异数OS TCP长连接技术简介 说起长连接,则首先要谈对 ...
随机推荐
- stm32串口发送数据复位 第一个数据丢失
http://blog.csdn.net/kevinhg/article/details/40991655 STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成 ...
- C语言顺序表
顺序表结构可设为一个数组和一个指向尾部的变量,数组用来存放元素,指向尾部的变量在插入元素的时候加一,删除元素的时候减一,始终指向尾部. typedef int elemtype; typedef st ...
- C++实现json字符串与map的转换
开源资源库 jsoncpp-src-0.5.0.tar.gz:https://sourceforge.net/projects/jsoncpp/ jsoncpp-master.ziphttps://g ...
- 嘿,C语言(持续更新中...)
---恢复内容开始--- 上次简单介绍了一下C语言,这次说说数据与计算程序,那么话不多说,进来看看. 第二章 数据与简单的计算程序 一:数据 既然说到了数据,那么说说什么是写数据呢? 表面意 ...
- 常用的go语言IDE对比
Go语言目前已经在开发者中越发的流行,自然很多人都在寻找合适的IDE来实现代码语法高亮.自动补全以及其他编辑特性. 下面就几种常用的IDE进行对比介绍: 1. Sublime text 这个文本编辑器 ...
- 156. Merge Intervals【LintCode by java】
Description Given a collection of intervals, merge all overlapping intervals. Example Given interval ...
- 怎样才能使用ChipScope 加入被优化掉的信号
在调试过程中常常遇到的一个问题就是,xilinx工具在逻辑综合的过程中,将自己RTL代码中的很多变量都优化掉了,使得调试的抓信号的过程很纠结.以下是解决方法: 1.右键synthesis,在综合选项里 ...
- JS日期转换
用js将从后台得到的时间戳(毫秒数)转换为想要的日期格式 得到后台从数据库中拿到的数据我们希望格式是 2016年10月25日 17时37分30秒 或者 2016/10/25 17:37:30 然而我们 ...
- OSG-CompositeViewer
原文连接地址:http://www.osgchina.org/index.php?Itemid=490&id=134:usecompositiv&option=com_content& ...
- django 与 flask里面从已有数据库表中反向生成models
django: 配置好数据库连接 python manage.py inspectdb > models.py 即可反向生成orm使用的models, 注意: > 后面可以定义为指定路 ...