TCP状态流转

本篇主要说说TCP的状态流转。本篇图片摘自《计算机网络 自顶向下方法》。

基础

在说TCP状态流转之前,需要先说一下TCP的连接与断开过程。

三次握手

TCP在连接的时候客户端与服务端连接的过程如下图:


三次握手.png

主要过程:

  • 客户端向服务端发送SYN包,发起连接请求
  • 服务端收到客户端的连接请求,并将seq+1(表示收到seq序列之前的数据),然后向客户端发送SYN+ACK包,表示服务端已经收到客户端的连接请求,并向客户端询问是否已准备好建立连接
  • 客户端收到服务端的SYN+ACK包,将服务端序列server_isn+1,然后向服务端发送ACK包,表示收到了服务端发送的SYN+ACK包

经过上述三个步骤,TCP连接建立。

补充一下,SYN包是发起连接的报文,ACK是答复报文(TCP的报文发出去是需要收到答复的,但不一定是每个包都答,而是一种累计确认的方式)。其他有关报文中的SYN、ACK标志位,seq序列号等内容,需详细看TCP报文结构,在此不赘述。

四次挥手

TCP是双工的协议,可以双向收发,单向关闭,所以TCP连接需要分别关闭两个方向,关闭每个方向均需FIN+ACK两次握手,共计四次。 TCP连接的关闭过程如下图:


四次挥手.png

主要过程

  • 客户端主动发起关闭,向服务端发送FIN包,表示客户端已经没有数据要发送给服务端了
  • 服务端收到客户端发送的FIN包,向客户段发送ACK包,表示收到FIN包
  • 当服务端也没有数据向客户端发送时,服务端向客户端发送FIN包,表示要关闭
  • 客户端答复ACK包,表示收到服务端发送的FIN包

经过上述四个步骤,TCP连接全部断开

上图中有个定时等待过程,会等待2MSL时间(Maximum Segment Lifetime,报文最大生存时间,任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃),TCP占用的端口才会被释放,所以大家有时会发现,TCP连接断开后,端口需要过一会才会释放。2MSL时间具体根据TCP的不同实现大概是1-4分钟。

等待2MSL的作用

  • 防止4次挥手最后一个ACK服务端没有收到,那么服务端还会重发FIN包
  • 防止之前发出去因为路由、网络导致没收到的包,最终又到达了目的地,此时若端口被新连接使用的话,则新连接会收到旧数据。

状态流转

客户端状态流转

image.png
  • CLOSED:TCP开始时处于CLOSED状态
  • SYN_SENT:客户端向服务端发起连接请求会发送一个SYN报文,此时客户端TCP处于SYN_SENT状态
  • ESTABLISHED: 客户端收到服务端答复的SYN+ACK报文后,连接建立,处于ESTABLISHED状态,此时客户端就可以和服务端收、发数据了
  • FIN_WAIT_1:当客户端发起关闭时,向服务端发送FIN报文,并等待服务端的答复报文,此时进入FIN_WAIT_1状态
  • FIN_WAIT_2:当客户端收到FIN_WAIT_1前发送的FIN报文对应的ACK报文后,进入FIN_WAIT_2状态
  • TIME_WAIT: 当客户端处于FIN_WAIT_2状态时,若收到服务端发送的FIN包时(服务端断开连接),客户端再向服务端发送ACK报文,此时进入TIME_WAIT状态,TIME_WAIT状态会等待2MSL时间,之后状态回到CLOSED

服务端状态流转

image.png
  • CLOSED:开始时处于CLOSED状态
  • LISTEN:服务端创建套接字并开始监听,此时服务端TCP处于LISTEN状态
  • SYN_RCVD:当客户端发起连接请求,服务端收到SYN包后(三次握手第一次),并向客户端发送SYN+ACK报文后(三次握手第二次),客户端TCP处于SYN_RCVD状态
  • ESTABLISHED:当服务端收到三次握手第三次客户端发送的ACK报文后,连接建立,此时进入ESTABLISHED状态
  • CLOSE_WAIT:当服务端收到客户端发送的断开连接请求FIN报文时,服务端会向客户端发送ACK报文,表示知道客户端不会再向服务端发送东西了,此时进入CLOSE_WAIT状态
  • LAST_ACK:当处于CLOSE_WAIT状态服务端需要关闭连接时会向客户端发送断开连接请求FIN报文,此时进入LAST_ACK状态,表示等待最后一个客户端发送过来的ACK报文,当收到最后一个ACK报文时,回到CLOSED状态

你可能感兴趣的:(TCP状态流转)