经过前面对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. 献给初学者:小白该如何学习Linux操作系统

    一. 选择适合自己的Linux发行版 谈到linux的发行版别,太多了,可能谁也不能给出一个准确的数字,但是有一点是能够必定的,linux正在变得越来越盛行, 面临这么多的Linux 发行版,打算从别 ...

  2. 动态链接库函数内的静态变量,奇妙的UNIQUE Bind

    title: 动态链接库函数内的静态变量,奇妙的UNIQUE Bind date: 2018-09-28 09:28:22 tags: --- 介绍 模板函数和内敛函数中的静态变量,在跨so中的表现, ...

  3. C语言学习记录_2019.02.04

    逻辑性变量的定义符:bool,在C语言中只有true和false: 定义方式:bool t = true; 逻辑运算符: !:逻辑非 &&:逻辑与 ||:逻辑或 表达区间的错误形式:4 ...

  4. malloc、calloc、realloc函数说明

    malloc 函数 #include <stdlib.h> void* malloc(int n); n为要分配的字节数,如果成功,返回获得空间的首地址,如果分配失败,则返回NULL,ma ...

  5. HBase简介(梳理知识)

    一. 简介 hbase是bigtable的开源山寨版本.是建立的hdfs之上,提供高可靠性.高性能.列存储.可伸缩.实时读写的数据库系统.它介于nosql和RDBMS之间,仅能通过主键(row key ...

  6. Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天、消息模块

    原文:Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天.消息模块 中秋节假期没事继续搞了搞 做了各聊天的模块,需要继续优化 第一步画页面 页面参考https://github.c ...

  7. C++三元操作符

    c++的三元操作符形式: //条件表达式 ? 表达式1 : 表达式2; 语义:如果“条件表达式”为true,则整个表达式的值就是表达式1,忽略表达式2:如果“条件表达式”为false,则整个表达式的值 ...

  8. 封装一个CSVHelper

    public class CSVHelper { /// <summary> /// CSV转换成DataTable(OleDb数据库访问方式) /// </summary> ...

  9. springboot shiro没有注解解决方案

    颓废的悠然   springboot shiro开启注释 shiroconfiguration中增加 1 2 3 4 5 6 7 @Bean     public AuthorizationAttri ...

  10. ORA-15032、ORA-15033—Linux环境

    SQL> alter diskgroup DATA add failgroup DATA_0000 disk '/dev/raw/raw12'; alter diskgroup DATA add ...