TCP三次握手、四次挥手

gong_yz大约 10 分钟计算机网络

传输控制协议TCP

传输控制协议 TCP (Transmission Control Protocol)一种基于连接的可靠的稳定的无重复的传输协议

1、TCP头部信息

TCP协议头部信息如下:

image.png
image.png
  • 16位源端口号(Source Port):发送主机中进程的端口号
  • 16位目的端口号(Destination Port):接收主机中进程的端口号
  • 32位序列号(Sequence Number):每一个包中都包含序列号,序列号被系统初始化为某个随机值ISN。后续的TCP报文段中序号加上该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个TCP报文段传送的数据是字节流中的第1025~2048字节,那么该报文段的序号值就是ISN+1025
  • 32位确认号(Acknowledgment Number):目的主机返回确认号,使源主机知道某个或几个报文段已被接收
  • 四位首部长度(Header Length):由于TCP首部包含一个长度可变的选项部分,所以需要这么一个值来指定这个TCP报文段到底有多长
  • URG标志:表示紧急指针(urgent pointer)是否有效
  • ACK标志:表示确认号是否有效。我们称携带ACK标识的TCP报文段为确认报文段
  • PSH标志:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在TCP接收缓冲区中)
  • RST标志:表示要求对方重新建立连接。我们称携带RST标志的TCP报文段为复位报文段
  • SYN标志:表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段
  • FIN标志:表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段为结束报文段
  • 16位窗口大小(window size) :是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度
  • 16位校验和(TCP check sum): 由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。
  • 16位紧急指针(urgent pointer) :是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法。
  • TCP头部选项 :TCP头部的最后一个选项字段(options)是可变长的可选信息。这部分最多包含40字节

2、TCP运输连接的阶段

  • 建立TCP连接
  • 数据传输
  • 释放TCP连接

注意:三报文握手我们也称之为三次握手或者三路握手,四报文挥手我们也称之为四次挥手或者四路挥手


3、TCP连接的建立

TCP连接的建立需要解决以下三个问题:

  • 使TCP双方能够确知对方的存在
  • 使TCP双方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)
  • 使TCP双方能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配

三次握手过程

  • 由客户端的某个进程主动发起TCP连接建立,最初两端的TCP进程都处于关闭状态

  • TCP服务器被动等待客户进程的TCP请求,所以TCP服务器进入监听状态

  • TCP客户进程向TCP服务器进程发送TCP建接请求报文段,并且进入同步已发送状态

  • TCP连接请求报文段首部中的同步位SYN被设置为1,表明这是一个TCP连接请求报文段,32位序列号字段seq被设置了一个初始值x,作为TCP客户进程所选择的初始序号。

  • TCP服务器进程接收到TCP连接请求报文段后,如果同意建立连接,则向TCP客户进程发送TCP连接请求确认报文段,并且进入同步已接收状态,该报文段首部中的同步位SYN和确认位ACK都设置为1,表明这是一个TCP连接请求确认报文段。序号字段seq被设置了一个初始值y,作为TCP服务器进进程选择的初始序号,确认号字段ack的值被设置成x+1,表明接收到了TCP客户进程序号为x的报文。

  • TCP客户进程收到TCP连接请求确认报文段后,还要向TCP服务器进程发送一个普通的TCP确认报文段,并且进入连接已建立状态,报文段首部中的确认位ACK设置为1,表明这是一个普通的TCP确认报文段。序列号字段seq设置为x+1,确认号字段ack的值被设置成y+1,表明接收到了TCP服务进程序号为y的报文,TCP服务器进程收到该确认报文段后也进入连接已建立状态

  • 思考:假如TCP连接的建立使用两次握手而不是三次握手可以吗?

    • 假设TCP客户进程发送了一个TCP请求报文段,但是该报文段在网络结点中被长时间滞留了,TCP客户采用超时重传机制重发TCP请求报文段并且被TCP服务进程接收,TCP服务进程发送一个TCP连接请求确认报文段,然后TCP服务进程和客户进程可以进行数据的传输,数据传输完成以后双方都处于关闭状态。
    • 随后滞留在网络结点中的那个失效的TCP请求报文段被TCP服务进程接收,TCP服务进程又发送一个TCP连接请求确认报文段,并且进入连接已建立状态,由于TCP客户进程并没有发起新的TCP连接请求,并且已经处于关闭状态了,因此不会理会TCP服务器发送的报文段,但是TCP服务器进程已经进入了连接已建立状态,他认为新的TCP连接已经建立好了,就会一直等待TCP客户进程发来数据,将会浪费TCP服务器主机的很多资源。
    • 【总结】如果没有第三次握手,服务机是不知道客户机初始化状态的,一旦服务机给客户机进行回复确认因网络波动等原因延时了,那么客户机可以反复执行请求,服务机不断地开辟空间为请求做回复,浪费了大量资源,这个恶意攻击叫**泛洪攻击**。
  • 因此:TCP连接的建立必须采用三次握手。

  • 练习:

四次挥手过程

TCP通过四次挥手来释放连接,数据通信结束后,TCP双方都可以释放连接

  • 假设由客户进程主动关闭TCP连接

  • 客户进程发送连接释放报文段,并且进入终止等待1状态,该报文段中的首部终止位FIN设置位1,ACK设置为1,表明这是一个连接释放报文段,同时也对之前接收打报文段进行确认,seq=u表示TCP客户进程之前已发送过的数据的最后一个字节的序号+1,ack=v表示客户进程之前已收到的数据的最后一个字节的序号+1

  • 服务器进程接收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段并且进入关闭等待状态,此时TCP客户进程到服务器进程这个方向的连接就释放了,这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了,但是TCP服务器进程如果还有数据需要发送,客户进程则还需要接收,这个状态可能会持续一段时间,直到TCP服务器进程将数据发送完毕。

  • TCP客户进程收到TCP确认报文段后就进入终止等待2状态,等待TCP服务器进程发出的TCP连接释放报文段。

  • 当TCP服务器进程的没有数据要发送了后,释放连接(被动关闭),TCP服务器进程发送TCP连接释放报文段并进入最后确认状态。FIN=1,ACK=1表明这是一个连接释放报文段,seq=w,ack=u+1同时也对之前收到的报文段进行确认。思考:为什么seq=w,而不是seq=v+1呢?**答:**因为TCP服务器可能还有数据需要向TCP客户端发送,所以seq=w是要大于v+1的,如果没有数据发送,就是seq=v+1

  • TCP客户进程收到TCP连接释放报文段后,必须针对该报文段发送普通的TCP确认报文段,之后进入时间等待状态

  • TCP服务器进程收到该报文段后就进入关闭状态

  • 而TCP客户进程还需要经过2MSL后才能进入关闭状态。MSL(Maximum Segment Lifetime)意思是最长报文段寿命,RFC793建议为2分钟

  • 思考:为什么TCP客户进程还需要经过2MSL后才能进入关闭状态?

    • 假设TCP客户进程收到TCP连接释放报文段,并且针对该报文段发送普通的TCP确认报文段后马上进入关闭状态,但是该确认报文段丢失了,TCP服务器进程无法收到该确认报文段,TCP服务器程序就会以为之前发送的TCP连接释放报文段TCP客户进程没有收到,然后TCP服务器进程会对之前所发送的TCP连接释放报文段超时重传,并仍处于最后确认状态。由于TCP客户进程已经处于关闭状态了,不会处理TCP服务器进程发送的连接释放报文段,这样就会造成TCP服务器反复发送TCP连接释放报文段,并且一直处于最后确认状态而无法进入关闭状态。因此客户端等待2MSL可以确保服务器进程收到最后一个TCP确认报文。