经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看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连接管理的状态机的更多相关文章

  1. TCP系列11—重传—1、TCP重传概述

    在最开始介绍TCP的时候,我们就介绍了TCP的三个特点,分别是面向连接.可靠.字节流式.前面内容我们已经介绍过了TCP的连接管理,接下来的这部分内容将会介绍与TCP可靠性强关联的TCP重传. 很多网络 ...

  2. TCP系列08—连接管理—7、TCP 常见选项(option)

    一.TCP选项概述 在前面介绍TCP头的时候,我们说过tcp基本头下面可以带有tcp选项,其中有些选项只能在连接过程中随着SYN包发送,有些可以延后.下表汇总了一些tcp选项 其中我标记为红色的部分是 ...

  3. TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接

    一.TCP连接的ISN         之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...

  4. TCP系列02—连接管理—1、三次握手与四次挥手

    一.TCP连接管理概述 正如我们在之前所说TCP是一个面向连接的通信协议,因此在进行数据传输前一般需要先建立连接(TFO除外),因此我们首先来介绍TCP的连接管理. 通常一次完整的TCP数据传输一般包 ...

  5. TCP系列03—连接管理—2、TCP连接的同时打开和同时关闭

    在前面的内容中我们介绍了TCP连接管理中最常见的三次握手方式和四次挥手的方式.但是有可能A和B两端同时执行主动打开并连接对方或者同时执行主动关闭连接(尽管发生这种情况的可能性比较低低),这个时候的流程 ...

  6. TCP系列04—连接管理—3、TCP连接的半打开和半关闭

    在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...

  7. SQL Server 连接问题-TCP/IP

    原文:SQL Server 连接问题-TCP/IP 出自:http://blogs.msdn.com/b/apgcdsd/archive/2012/02/24/ms-sql-server-tcp-ip ...

  8. 小tips:TCP的三次握手、长连接、 短连接、 SPDY 协议

    当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需 ...

  9. 异数OS TCP协议栈测试(三)--长连接篇

    异数OS TCP协议栈测试(三)--长连接篇 本文来自异数OS社区 github:   异数OS-织梦师(消息中间件)群: 476260389 异数OS TCP长连接技术简介 说起长连接,则首先要谈对 ...

随机推荐

  1. C# string 转 byte[]

    string 转 byte[] /// <summary> /// string 转 byte /// </summary> /// <param name=" ...

  2. Python3 urllib 与 Python2 urllib的变化

    Infi-chu: http://www.cnblogs.com/Infi-chu/ Py2.x: Urllib库 Urllin2库 Py3.x: Urllib库 变化: 在Pytho2.x中使用im ...

  3. python--基本类型之集合

    set(集合): 定义和创建: 定义:集合是一个无序的,不重复的数据集合,它主要作用1:去重,把一个列表变成集合,就自动去重了2:关系测试,测试两组数据之间的交集,差集,并集等关系 集合:把不同的数据 ...

  4. 滑雪_KEY

    滑雪 ( skiing.pas/c/cpp) [题目描述] MM 参加一个滑雪比赛,滑雪场是一个 N×M 的矩形, MM 要从起点( 1, 1)滑到( N,M).矩形中每个单位格子有一个海拔高度值 h ...

  5. mongoDB在java上面的应用

    1.实际应用过程中肯定不会直接通过Linux的方式来连接和使用数据库,而是通过其他驱动的方式来使用mongoDB 2.本教程只针对于Java来做操作,主要是模拟mongoDB数据库在开发过程中的应用 ...

  6. sphinx生成cakephp文档

    cakephp的文档是用一个叫sphinx程序生成的 这个程序是python写的,所以我们要用sphinx本机必须先装python. 编译过程在Ubuntu下进行,默认Ubuntu已经安装了pytho ...

  7. oradebug 的学习 一

        说明 oradebug主要是给oracle支持人员使用的,尽管很早便有,但oracle官网很少有记载.他是个sql*plus命令行工具,有sysdba的权限就可以登入,无需特别设置.他可以被用 ...

  8. 从零学习安全测试,从XSS漏洞攻击和防御开始

    WeTest 导读 本篇包含了XSS漏洞攻击及防御详细介绍,包括漏洞基础.XSS基础.编码基础.XSS Payload.XSS攻击防御. 第一部分:漏洞攻防基础知识   XSS属于漏洞攻防,我们要研究 ...

  9. uvaoj 489 - Hangman Judge(逻辑+写代码能力)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  10. AirtestIDE实践一:梦幻西游手游师门任务自动化

    Airtest Project是网易自研的游戏自动化项目.Airtest IDE是这个项目的一个IDE,就像Eclipse.Pycharm一样,是一个集成开发工具.Airtest框架是一个基于Open ...