一个TCP连接在其生命周期中经过了一系列的状态跃迁。一个TCP连接的状态包括:
- LISTEN :表示正在等待来自任何远程TCP和端口的连接请求,调用listen后套接字出于监听状态
- SYN_SENT : 表示在发送了连接请求后,正在等待匹配的连接请求。(发送SYN后没有收到ACK)
- SYN_RECV : 表示在收到和发送连接请求后,等待确认连接请求确认。(收到对方发送的SYN,但还没有收到自己发送SYN的ACK)
- ESTABLISHED : 表示一个开放的连接,接收到的数据可以传递给用户。连接的数据传输阶段的正常状态。
- FIN-WAIT-1 : 表示正在等待来自远程TCP的连接终止请求,或确认先前发送的连接终止请求。(发送FIN, 没有收到ACK也没有收到FIN)
- FIN-WAIT-2 : 表示正在等待来自远程TCP的连接终止请求
- CLOSE-WAIT : 表示正在等待来自本地用户的连接终止请求。(被动关闭的一方收到FIN,发送ACK)
- CLOSING : 表示正在等待来自远程TCP的连接终止请求确认。(在FIN-WAIT-1状态下收到了FIN, 等待接收ACK的确认)
- LAST-ACK : 表示等待对先前发送到远程TCP的连接终止请求的确认(其中包括对其连接终止请求的确认)
- TIME-WAIT : 表示正在等待足够的时间通过,以确保远程TCP收到了对其连接终止请求的确认。
- CLOSED : 表示根本没有任何连接状态。虚拟的一个状态
按TCP/IP协议的描述,TCP三次握手过程,TCP的状态迁移如下所示:
(1)客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端确认。
(2)服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
(3)客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
注意:我们上面写的ack和ACK,不是同一个概念:
备注: 小写的ack代表的是头部的确认号Acknowledge number, 缩写ack,是对上一个包的序号进行确认的号,ack=seq+1。
大写的ACK,则是我们上面说的TCP首部的标志位,用于标志的TCP包是否对上一个包进行了确认操作,如果确认了,则把ACK标志位设置成1。