TCP三次握手、四次挥手

前言

想要彻底理解TCP三次握手,四次挥手,一定要认识TCP的首部以及各个字段的意义。主要是序号(seq)、确认号(ack)和控制号。这里我只介绍前面那几个字段的意义,其他的看书(谢希仁的计算机网络课本)。

TCP首部格式

TCP首部

序号

占4个字节,序号范围是[0 , 2^32-1],共2^32(即4294967296)个序号。序号增加到2^32-1后,下一个序号又回到0。也就是说序号使用mod 2^32-1TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都是按顺序编号的。整个要传送的字节流的起始序号必须在建立连接时设置。首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号。例如,一报文的序号字段值是301,而携带的数据共有100字节。这就表明:本报文段的数据的第一个字节序号是301,最后一个字节序号是400。显然,下一个报文段的数据序号应该从401开始,即下一个报文段的序号字段值应该是401.这个字段的名臣也叫做“报文段序号”。

确认号

占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号

1
若确认号 = N , 则表明:到序号N-1为止的所有数据都已经正确收到了。

下面是6个控制位

紧急URG(URGent)

当URG = 1时,表明紧急指针字段有效。他告诉系统此报文中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序要传送。当URG置1时,发送应用进程就告诉对方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。这时就要与首部中的紧急指针(urgent pointer)字段配合使用。

确认ACK(ACKnowledgment)

仅当ACK=1时,确认号(ack)字段才有效。当ACK=1时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。

同步SYN(SYNchronization)

在建立连接时用来同步序号。

1
2
3
SYN=1
ACK=0
表明这是一个连接请求报文段
1
2
3
若同意建立连接,则应在相应的报文段中使:
SYN = 1
ACK = 1

因此,SYN置为1就表示这是一个连接请求或连接接受报文。

终止FIN(FINis)

用来释放一个连接,当FIN=1时,表明次保温段的发送方数据已经发送完毕,并要求释放运输连接。

推送 PSH(PuSH)

当两个应用进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的相应。在这种情况下,TCP就可以使用推送(push)操作。这是,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地交付接受应用进程,而不再等到整个缓存都填满了再向上交付。

复位RST(ReSeT)

当RST=1时,表明TCP连接中出现严重错误,必须释放连接,然后再重新建立运输连接。RST置1还用来拒绝一个非法的报文段或者拒绝一个连接。RST也可称为重建位或重置位。

三次握手

TCP建立连接的过程叫做握手,握手需要在客户端和服务器之间交换三个TCP报文段。

三次握手示意图:

TCP三次握手

三次握手过程:

1
2
3
4
5
6
//服务器处于监听状态,当客户端想与服务器建立连接时,操作流程如下:
客户端->服务端 SYN = 1 客户端进入同步已发送状态
//若服务端同意连接,操作流程如下:
服务端->客户端 SYN = 1 , ACK = 1 服务端进入同步收到状态
客户端->服务端 ACK = 1 客户端进入ESTABLISHED(已建立连接状态)
服务端收到客户端的确认后,也进入ESTABLISHED状态。

为什么客户端最后还要发送一次确认:

  • 这是为了防止已经失效的连接请求报文段突然有传送到了服务端,重新建立了一个连接,因而产生错误和资源浪费。
  • 所谓“已失效的链接请求报文段”是这样产生的,考虑一种正常情况,客户端发出连接请求,但因为连接请求报文丢失而未收到确认。于是客户端再重传了一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。客户端共发送了2个连接请求报文段,其中第一丢失,第二个到达了服务端,没有“已失效的连接请求报文段”。
  • 现假定一种异常情况,即客户端发出第一个请求连接报文段并没有丢失,而是滞留在某个网络节点,以致延误到链接释放后的某个时间才到达服务端。本来这是一个早就失效的报文段。但服务端收到此失效的报文段后,就误认为客户端又发了一次新的连接请求。于是向客户端发出了确认报文段,同意建立连接。假定不采用报文握手,那么只要服务端发出确认,新的连接就建立了。

四次挥手

数据传输结束后,通信双方都可释放连接。假设客户端先向其TCP发出释放连接报文段,并停止再发送数据,主动关闭TCP连接

四次挥手过程图:

TCP四次挥手

四次挥手过程:

1
2
3
4
5
6
7
客户端->服务端	FIN = 1 			客户端进入中止等待1状态
服务端->客户端 ACK = 1 服务端进入关闭等待状态
//此时TCP进入半关闭状态,服务端继续向客户端发送数据,当数据发送完毕之后
服务端->客户端 FIN = 1 , ACK = 1 服务端进入最后确认状态
//客户端收到确认后,必须对此发出确认
客户端->服务端 ACK = 1 客户端进入时间等待状态
服务端收到确认后关闭连接,客户端必须经过时间等待计时器设置的2MSL后,客户端才进入closed状态。

为什么客户端在时间等待状态必须等待2MSL的时间:

  • 第一,为了保证客户端发送的最后一个ACK能到达服务端。
  • 防止上文提到的“已经失效的链接请求报文段”出现在本连接中。