一、TCP连接的建立
TCP 是面向连接的,在传输 TCP 报文段之前先要创建连接,发起连接的一方被称为客户端,而响应连接请求的一方被称为服务端,而这个创建连接的过程被称为三次握手 :
-
客户端发出请求连接报文段,其中报头控制位
SYN=X
。 -
服务端收到请求报文段后,向客户端发送确认报文段。确认报文段的首部中
ACK=X+1
,同时在同一个包中包含自己的SYN=Y
。 -
客户端收到服务端的确认报文段后,还要给服务端发送一个确认报文段。这个报文段中
ACK=Y+1
。
至此 TCP 连接已经建立,客户端进入 ESTABLISHED
(已建立连接)状态,当服务端收到确认后,也进入ESTABLISHED
状态,它们之间便可以正式传输数据了。
二、TCP连接的释放
当传输数据结束后,通信双方都可以释放连接,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭,这个释放连接过程被称为四次挥手 :
-
此时 TCP 连接两端都还处于
ESTABLISHED
状态,客户端停止发送数据,并发出一个FIN
报文段。 -
服务端回复确认报文段,确认号
ack=FIN+1
。现在 TCP 连接处于半开半闭状态,服务端如果继续发送数据,客户端依然接收(因为只关闭了一个方向:客户端到服务端)。 -
服务端发送完数据后,发出
FIN
报文段,然后进入LAST-ACK
(最后确认)状态。 -
客户端回复确认确认报文段,
ACK=FIN+1
,然后进入TIME-WAIT
(时间等待)状态。
注意此时连接还没有释放,需要时间等待状态结束后(4 分钟) 连接两端才会 CLOSED。设置时间等待是因为,有可能最后一个确认报文丢失而需要重传。
三、为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN
状态下的SOCKET
当收到SYN
报文的建连请求后,它可以把ACK
和SYN
(ACK
起应答作用,而SYN
起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN
报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET
,也即你可能还需要发送一些数据给对方之后,再发送FIN
报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK
报文和FIN
报文多数情况下都是分开发送的。
网友评论