TCP 的运输连接管理
TCP 是面向连接的协议,运输连接是用来传送 TCP 报文的,TCP 的运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,运输连接就有三个阶段,即:连接建立、数据传输、连接释放。
TCP 的连接建立
TCP 连接的建立采用客户服务器的方式。主动发起连接建立的应用进程叫做客户(client),而被动等待连接建立的应用进程叫做服务器(server)。
TCP 在建立连接的过程中是采用了三次握手
的机制,是指 TCP 在建立连接的过程中分为三个阶段(握手需要在客户和服务器之间交换三个 TCP 报文段)。
- 第一次握手(SYN):客户端向服务器发送报文段,这时首部的同步位 SYN = 1,告诉服务器想要连接,同时选择一个初始序号 seq = x。注意:TCP 规定,SYN 报文段(即 SYN = 1 的报文段)不能携带数据,但是要消耗掉一个序号。 客户端进程进入
SYN-SENT
(同步已发送)状态。 - 第二次握手(SYN + ACK):服务器接收到请求报文段后,向客户端确认,在确认报文段中把 ACK 置为 1 ,表示确认连接,把 SYN 也置为 1,表示接收建立连接。确认号为 ack = x + 1。注意:该报文段也是不携带数据的,但同样消耗一个序号。 服务器进程此时进入
SYN-REVD
(同步收到)状态。 - 第三次握手(ACK):客户端收到服务器发来的 SYN + ACK 报文段后,客户端还会给服务器发送一个确认报文段(ACK 报文段),告诉服务器已经建立了连接,可以开始传输数据了。此时 TCP 连接已经建立,客户端进程进入了
ESTABLISHED
(已建立连接)状态。
如果说三次握手,少了最后一次握手可以吗?
不可以,会浪费资源。
防止恶意连接,如歌没有第三次握手,当发送客户端发送请求报文段的时候在某个网络节点长时间滞留了,导致客户端重发了一个连接,如果没有第三步的话,那客户端发送的第二个连接收到服务器的 SYN-ACK 报文段后就确定连接了,开始发送数据然后释放连接。这个时候滞留的连接到服务器端然后发送了 SYN-ACK 报文段,服务器则表示已经连接了,等待数据传输,然而并没有数据,则浪费了资源。
如果第三次握手存在的话,那则当客户端发送了 ACK 报文段后才确定已连接。那即使那个连接滞留后才到,也会因为客户端没有发送 ACK 报文段而表示连接未建立成功。所以说第三次握手也是需要的。
半连接队列和全连接队列
服务器第一次收到客户端的连接请求(SYN)后,进程会处于 SYN_RCVD 状态,此时双方还没有完全建立连接,服务器会把此状态下的连接放到一个队列中,把这种队列称为半连接队列。
已经完成三次握手后,建立起来的连接就会放到全连接队列中。 如果队列满了就可能出现丢包现象。
SYN-ACK 重传问题
当服务器发送SYN-ACK 报文段的时候,如果未收到客户确认包(第三次握手),那么服务器会进行首次重传,反复重传次数超过系统规定的最大传送次数后,系统会将该连接信息从半连接队列中删除。
TCP 的连接释放
客户端当数据传输完毕,需请求关闭连接称为 TCP 连接的释放。
TCP 的连接释放需要经过四次挥手(四个报文段)。TCP 是提供全双工通信的, 也就是释放连接得释放两端互相的连接。而前俩次挥手只是让 TCP 处于半关闭状态,半关闭是通知应用程序已经无数据传输了。
- 第一次挥手:客户端向服务器端发送 FIN 报文段,这时客户端进程进入了
FIN-WAIT-1(终止等待1)
状态。 - 第二次挥手:服务器收到 FIN 报文段后,发送 ACK 报文段给客户端,这时服务器进程是
CLOSE_WAIT(关闭等待)
状态。客户端收到 ACK 报文段后就实现了半关闭状态,此时客户端进入FIN_WAIT-2
状态。 - 第三次挥手:若服务器想要关闭服务器到客户端的连接(就是使得服务器不能向客户端发送数据了),则进行第三次挥手,向客户端发送 FIN 报文段。此时服务器端进程状态为
LAST_ACK(最后确认)
状态。 - 第四次挥手:收到 FIN 报文段后,向服务器端发送 ACK 报文段。这时客户端进程的状态为
TIME -WAIT(时间等待)
。此时连接并未释放,经过时间等待器设置的时间2MSL
后,客户端进程为CLOSED
状态。此时 TCP 链接释放完毕。
时间等待器需要的原因
设置时间等待器是为了客户端发送的最后一个 ACK 能到达服务器端。也就是说服务器端结束 TCP 连接的时间应该比客户端要早一些,让服务器端收到客户端发到的确认后,服务器端进入关闭状态,随后时间到了客户端再进入到关闭状态。