TCP状态机-状态解析

在网络协议栈中, 目前只有tcp提供了一种面向连接的可靠性数据传输。 而可靠性,无非就是保证,我发给你的,你一定要收到。确保中间的通信过程中,不会丢失数据和乱序。 在TCP保证可靠性数据传输的实现来看, 超时重传、序列号及数据的应答 这三个特征 就是实现可靠性的最基本保证,而对于tcp窗口大小等等设置,也是保证可靠性的一个方面。所有的目的只为一个,保证传输数据的完整性。 为了解决传输线路的不稳定性造成数据包的丢失情况,tcp 使用了发送方超时重传和接收方数据应答的策略。概括而言,就是一种“状态协议“,保证通信双方数据收发的一致性。

借助网上的一个状态图

TCP状态机-状态解析_第1张图片


下面简析一下 TCP的各个状态。

TCP_CLOSE:关闭状态, 一个新建的TCP socket 会处于该状态。

TCP_LISTEN: 监听状态,一般服务器端套接字在调用Listen系统调用后即处于该状态。

TCP_SYN_SENT:同步信号已经发送状态,这个状态一般是指客户端发送SYN(建立连接的同步)数据包后所处的状态(tcp三次握手的第一个包)。在接收到远端服务器端的应答后,即从该状态进入TCP_ESTABLISHED状态。

TCP_SYN_RECEIVED:同步信号已经接受状态,服务器端在接受到远端客户端SYN数据包后,进行相应的处理(创建通信套接字等),然后发送应答数据包(tcp三次握手的第二个包),并将新创建的通信套接字状态设置为TCP_SYN_RECEIVED,在接受到客户端的应答后,即进入TCP_ESTABLISED状态。

TCP_ESTABLISED:建立连接状态,这是双方进行正常通信所处的状态。

TCP_FIN_WAIT_1:本地发送FIN(用于结束连接的)数据包后即可进入该状态,等待对方的应答。一般一端发送完其所要发送的数据后,即可发送FIN数据包,此时发送通道被关闭,但仍可继续接受远端发送的数据包。在接受到远端发送的对于FIN数据包的应答后,将进入TCP_FIN_WAIT_2状态。

TCP_FIN_WAIT_2:进入该状态表示本地已经接受到远端发送的对于本地之前发送的FIN数据包的应答。进入该状态后,本地仍然可以继续接受远端发送给笨的的数据包。在接受到远端发送的FIN数据包后(表示远端也已经发送完数据),本地将发送一个应答数据包,并进入TCP_TIME_WAIT状态。TCP_TIME_WAIT状态存在的时间被称为2MSL时间,这一方面是为避免本地发送的应答数据包丢失,另一方面避免一个新创建的套接字接收到旧套接字中遗留的数据包。

TCP_TIME_WAIT:该转状态呗称为2MSL等待状态。如果在此期间接收到远端发送的FIN数据包,则表示之前在TCP_FIN_WAIT_2状态发送的ACK应答数据包在传输中丢失或者长时间被延迟,从而造成了远端重新发送了FIN数据包,此时重复ACK应答数据包。一旦2MSL时间到期,则将进入TCP_CLOSED状态,即完成关闭操作。

TCP_CLOSE_WAIT:该状态存在于后关闭的一端。当接收到远端发送的FIN数据包后,本地发送一个ACK应答数据包,并将该套接字状态从TCP_ESTABLISED设置为TCP_CLOSE_WAIT。本地可以继续向远端发送数据包,在发送完所有的数据后,本地将发送一个FIN数据包关闭本地发送通道,并将状态设置为TCP_LAST_ACK状态,等待远端对FIN数据包的应答数据包。

TCP_CLOSING:如果通信双方同时发送FIN数据包,则同时进行关闭操作,则双方将同时进入TCP_CLOSING状态。具体的,本地发送一个FIN数据包以结束本地数据包发送,如果在等待应答期间,接收到远端发送的FIN数据包,则本地将状态设置为TCP_CLOSING状态。在接收到应答后,再继续装入到TCP_CLOSE_WAIT状态。

TCP_LAST_ACK:作为后关闭的一方,在发送FIN数据包后,即进入TCP_LAST_ACK状态。此时等待远端发送应答数据包,在接收到应答数据包后,即完成关闭操作,进入TCP_CLOSE状态。

下面的代码是对应的状体。

enum {
  TCPF_ESTABLISHED = (1 << 1),
  TCPF_SYN_SENT  = (1 << 2),
  TCPF_SYN_RECV  = (1 << 3),
  TCPF_FIN_WAIT1 = (1 << 4),
  TCPF_FIN_WAIT2 = (1 << 5),
  TCPF_TIME_WAIT = (1 << 6),
  TCPF_CLOSE     = (1 << 7),
  TCPF_CLOSE_WAIT = (1 << 8),
  TCPF_LAST_ACK  = (1 << 9),
  TCPF_LISTEN    = (1 << 10),
  TCPF_CLOSING   = (1 << 11) 
};



你可能感兴趣的:(TCP状态机-状态解析)