一、TCP连接管理概述

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

通常一次完整的TCP数据传输一般包含三个阶段,分别是连接建立(setup)、数据传输(established)和连接释放(teardown 也称为cleared 或 terminated)。连接管理部分的主要内容则是TCP连接建立与连接释放的方式以及TCP连接状态(connection state)的管理,另外在建立TCP连接的过程中,在发送端和接收端会交换一些选项(option),其中一些选项只能在建立连接的过程中进行交换,有一些则可以在随后的数据传输中进行交换,因此我们也会分别简单介绍一下这些常见的选项。

在TCP的连接建立过程中一般需要处理下面三个问题

  1. 要使每一方能够确知对方的存在。
  2. 要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。
  3. 能够对传输实体资源(如缓存大小等)进行分配

TCP建立连接最常见的方式就是通过三次握手(three-way handshake),连接释放最常见的方式则是四次挥手(four-way handshake或four-way wavehang),下面我们先介绍这两种最常见的连接管理机制。

二、三次握手

三次握手的整个过程如下图所示,一般我们称呼主动发起连接(Active Opener)的一端为客户端(Client)被动等待连接(Passive Opener)的称为服务器端(Server)。此处我们说的客户端和服务器端和我们在WEB开发中使用客户端和服务器端的概念略有差异,WEB开发中一般称呼用户侧为客户端,后台为服务器端,但是后台的服务器端也可以主动向客户端发起TCP连接(尽管这种场景少一些),这个时候后台服务器也就相当于我们下图中的客户端了。

d

下面我们介绍一下整个过程

  • A和B的初始状态都是关闭状态,B进入LISTEN状态后被动打开,此时B等待接收客户端的SYN包建立连接。
  • A主动打开时,A 的 TCP 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,选择序号 seq = x,表明传送报文时的第一个字节序号是 x,由于SYN标志在逻辑上占用一个系列号,因此实际数据传输的时候,TCP传输的数据中第一个Byte对应的系列号为x+1。这个SYN包发送以后,A则进入SYN_SENT状态,等待B回复ACK确认包。
  • B 的 TCP 收到连接请求报文段后,则发回确认。B 在确认报文段中应使 SYN = 1,使标志位 ACK = 1, 其确认号ack = x + 1,自己选择的序号 seq = y。记得我们之前说过序列号SN实际代表传输了多少比特的数据净荷,实际上在TCP的SYN包中一般并不携带数据,但是由于SYN包和FIN包在协议规定在逻辑上面占1个Byte,因此B在接收到这个SYN包后回复的ack=x + 1。后面我们会讲到消耗系列号SN就意味着这个数据包一旦丢失可以进行重传操作,由于SYN消耗一个byte的系列号,因此SYN数据包丢失的时候是会触发重传的。在B收到A的SYN包并且发送ACK确认包后,B则进入SYN_RCVD状态。
  • A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1。此时A进入ESTABLISHED状态,A 的 TCP 通知上层应用进程,连接已经建立。
  • B 的 TCP 收到主机 A 的确认后,B也进入ESTABLISHED状态,同时通知其上层应用进程当前TCP 连接已经建立。

一般来说上面用来建立连接的初始系列号ISN(即x和y)的值是随机选取的,后面的文章会简单介绍ISN的生成。

三、四次挥手

数据传输结束后,通信的双方都可释放连接。现在如下图假设A 的应用进程先向其 TCP 发出连接释放报文段,并停止发送数据,主动关闭 TCP连接。则四次挥手的过程如下图所示

四次挥手释放连接的流程如下

  • 初始状态下A和B都是处于ESTABLISHED状态,当应用层没有待发数据而指示A关闭TCP连接的时候,A 设置连接释放报文段首部的标志位 FIN = 1,ACK=1,其序号seq = u,确认号ack=v,等待 B 的确认。此时A进入FIN_WAIT_1状态
  • B 收到A的FIN包的时候,发出确认,由于FIN包与SYN包类似都在逻辑上占1byte,因此确认号 ack = u + 1,而这个报文段自己的序号 seq = v。此时B进入CLOSE_WAIT状态,TCP 服务器进程通知高层应用进程。
  • 当A收到B的ACK确认包后,A进入FIN_WAIT_2状态,关于这个状态我们后续在进一步介绍。
  • 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。B 设置连接释放报文首部的FIN=1,ACK=1,报文序列号seq=v,确认号ack=u+1。此时B进入LAST_ACK状态。
  • A 收到连接释放报文段后,必须发出确认,在确认报文段中 ACK = 1,确认号 ack = v + 1,自己的序号 seq = u +1。 此时A进入TIME_WAIT状态。在TIME_WAIT状态下,A经过2MSL时间后就进入关闭状态,关于TIME_WAIT状态我们后续进一步介绍。
  • 在B接收到A的确认包后,B立即进入关闭状态。A和B都进入关闭状态后整个TCP连接释放。

四、三次挥手

在四次挥手关闭TCP连接的时候,有时会省略第二条ACK消息,只存在第一条FIN消息、第三条FIN+ACK消息以及第四条FIN消息,从上图四次挥手的过程中可以看到其实第二条消息的ACK Number和第三条消息的ACK Number是相同的,省略第二条的时候其实是第三条消息捎带了第二条消息的ACK,后面完整介绍TCP的状态机的时候,会看到这种省略第二条消息的状态消息。

五、wireshark抓包

对于上面讲到的三次握手和四次挥手,通过wireshark抓包来观察一下

其中进行连接的两个socket(还记得我们前面章节说过一个ip地址+一个端口构成一个socket,或者叫做endpoint吧),一个是127.0.0.1:49324,对应我们前面示意图中的active opener和active closer,另外一个socket是127.0.0.1:9877,则对应passive opener和passive closer。注意wireshark中的系列号Seq呈现的是相对值,所以第一条消息会呈现Seq=0,实际值为0xbc069a3b。wireshark图中[SYN, ACK]表示TCP头中SYN标志位和ACK标志位有效,[SYN]、[FIN, ACK]等含义类似。将wireshark中SYN、FIN两个标志位,以及系列号Seq、应答号Ack与前面的示意图对应起来观察一下吧。

对于三次挥手的情况,wireshark抓包如下为了使两端的seq更容易区分,三次握手后我从client端向server端传输了10bytes数据,如下图高亮的条目所示,传输10bytes后进行三次挥手的TCP连接终止的过程

补充说明

1.TCP连接的建立和终止可以参考RFC793协议

2.第二版<TCP/IP Illustrated Volume1>中给出的四次挥手过程中最后一条消息的seq是错误的

TCP系列02—连接管理—1、三次握手与四次挥手的更多相关文章

  1. tcp建立连接为什么需要三次握手和四次挥手

    前言 众所周知tcp传输层协议在建立连接的时候需要三次才能建立起一个真正的可靠连接,可是为什么是三次呢,不可以是两次,四次等等呢,可以自己思考一番,带着疑问可以看下文. 三次握手 在<计算机网络 ...

  2. TCP基础知识(二)三次握手与四次挥手

    TCP详解(2):三次握手与四次挥手 TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接,就好像你 ...

  3. 可靠的TCP连接为何是三次握手和四次挥手

    首先,咱们先来熟悉下经典的tcp/ip模型. tcp/ip 模型为了方便使用,将osi七层模型划分成了四层,分别为网络接口层,网络层,传输层,应用层. 他们作用分别为: 1)网络接口层:主要作用是将i ...

  4. TCP:与UDP区别、三次握手、四次挥手、Socket 编程

    1. TCP 基本认识 TCP 头部格式 为什么需要 TCP 协议?TCP 工作在哪一层? 什么是 TCP ? 什么是 TCP 连接? 如何唯一确定一个 TCP 连接呢? 有一个 IP 的服务器监听了 ...

  5. Tcp/Ip--正常情况下的三次握手,四次挥手

    三次握手 四次挥手

  6. TCP的三次握手和四次挥手图解

     1. TCP建立连接的三次握手 (1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确 ...

  7. 面试官求你了,别再问我TCP的三次握手和四次挥手

    少点代码,多点头发 本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 三次握手建立链接,四次挥手断 ...

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

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

  9. TCP连接的建立与释放(三次握手与四次挥手)

    TCP连接的建立与释放(三次握手与四次挥手) TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,HTTP协议 ...

随机推荐

  1. MySQL至TiDB复制延迟监控

    因生产环境mysql中有较多复杂sql且运行效率低,因此采用tidb作为生产环境的从库进行部分慢sql及报表的读写分离.其中MySQL至TIDB采用Syncer工具同步.关于TIDB的安装及Synce ...

  2. 微信支付tp5.1集合

    多商户号微信支付 配置 自己改一改 逻辑 就好了! 写的菜 勿喷 extend下面 主要目录 多商户号 配置项 根据自己的需求更改 可能有一些地方存在BUG 自己调试一下 就OK了,别像一个麻瓜一样 ...

  3. thinkphp5使用workerman定时器定时爬取某站点新闻资讯等内容

    1.首先通过 composer 安装workerman,在thinkphp5完全开发手册的扩展->coposer包->workerman有详细说明: #在项目根目录执行以下指令compos ...

  4. Celery的基本使用

    Celery 1.什么是Celery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度. 用Python写的执行 定时任务和异步任务的框 ...

  5. HyperLedger Fabric 1.4 问题汇总(16)

    16.1 在运行e2e_cli例子时,执行./network_setup.sh up,出现错误:网络搭建之network e2ecli_default not found 问题原因: End-2-En ...

  6. Java基础——注解

    一.概述 引自百度百科: 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法. ...

  7. Luogu P3120 [USACO15FEB]牛跳房子(金)Cow Hopscotch (Gold)

    题目传送门 这是一道典型的记忆化搜索题. f[x][y]表示以x,y为右下角的方案数. code: #include <cstdio> #define mod 1000000007 usi ...

  8. <简明>Markdown指南

    什么是Markdown?Markdown是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitHub 和技术问答网站 StackOverFlow 的御用书写格式. ...

  9. 老曹眼中的Linux基础

    Linux 几乎无处不在,不论是服务器构建,还是客户端开发,对操作系统的基本理解和基础技能的掌握对全栈来说都是必备的. 系统的选择 Linux发行版本大体分为两类,一类是商业公司维护的发行版本,一类是 ...

  10. ORB-SLAM(五)KeyFrameDataBase类

    关键帧数据库通过预先训练好的词典,维护一个向量std::vector<list<KeyFrame*> > mvInvertedFile; 该向量中mvInvertedFile[ ...