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


    一、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是错误的

     





  • 相关阅读:
    截除数值,分别获取数据与单位
    angularjs判断对象值是否存在
    angularjs文件上传实例
    获取Zxing.net 中所有barcodeformat
    创建QR CODE
    QR Code的容错级别
    验证QR Code版本
    Web API返回自定义数据给客户端
    理解Hive 不同组件的功能
    tcpdf中文解决方案
  • 原文地址:https://www.cnblogs.com/lshs/p/6038459.html
Copyright © 2020-2023  润新知