TCP的三次握手和四次挥手

288 阅读4分钟

三次握手

第一次握手:客户端发送标志位[SYN=1]序号[seq=x]的报文,请求建立连接。之后,客户端从“CLOSED”进入“SYN-SEND”,服务器被迫打开从“CLOSED”进入“LISTEN”。

第二次握手:服务器发送标志位[SYN=1,ACK=1]序号[seq=y,ack=x+1]的报文,确认客户端的seq有效,并同意创建新连接。之后,服务器从“LISTEN”进入“SYN-RCVD”。

第三次握手:客户端发送标志位[ACK=1]序号[seq=x+1,ack=y+1]的报文,确认收到服务器同意连接的序号。之后,客户端从“STN-SEND”进入“ESTABLISHED”,服务器从“SYN-RCVD”进入“ESTABLISHED”。

为什么建立连接时候,要进行第三次握手?

原因:第三次握手可以减少服务器的开销和资源浪费

假设现在是“两次握手”就成功的情况下建立链接:

1、第一次请求:客户端向服务器发起建立连接请求,由于网络原因迟迟未到服务器,客户端一般会设置一个超时时间,这种情况下就会关闭第一次连接请求的创建,重新发起第二次请求连接。

2、第二次请求:客户端向服务器发起建立连接请求,这次正常到达了服务器,服务器也做出了响应,第二次握手成功,就开启端口建立连接。

3、网络延迟的第一次请求:在过了一段时间后,延迟的第一次请求终于到达了服务器,服务器也做出了响应,第二次握手成功,又开启端口建立连接,但是由于客户端已经关闭了对第一次请求连接的创建,这个连接就再也不会有数据传回服务器,但是服务器又不知道,该端口就会一直开着。

4、网络延迟导致的超时重传连接多了,就会照成服务器开启过多端口处理一些失效的连接,导致服务器资源浪费。

所以,客户端才需要第三次握手来告诉服务器,有没有收到第二次握手时服务器发送的数据,有则建立TCP连接,没有则建立TCP连接失败,服务器也会关闭相应的连接端口。

四次挥手

第一次挥手:客户端发送标志位[FIN=1]序号[seq=x]的报文,请求释放连接,客户端从“ESTABLISHED”进入“FIN-WAIT-1”。

第二次挥手:服务器发送标志位[ACK=1]序号[seq=y,ack=x+1]的报文,确认收到释放连接请求,服务器从“ESTABLISHED”进入“CLOSE-WAIT”,客户端从“FIN-WAIT-1”进入“FIN-WAIT-2”。

第三次挥手:服务器发送标志位[FIN=1,ACK=1]序号[seq=z,ack=x+1]的报文,同意释放连接,服务器从“CLOSE-WAIT”进入“LAST-ACK”。

第四次挥手:客户端发送标志位[ACK=1]序号[seq=x+1,ack=z+1]的报文,确认收到同意释放连接请求,服务器从“LAST-ACK”进入“CLOSED”,客户端等待2MSL时间,再从“FIN-WAIT-2”进入“CLOSED”。

为什么释放连接时候,要进行四次挥手而不是三次?

原因:服务器释放连接前有必要数据需要处理

建立连接和释放连接服务器始终都是被动方,建立连接的时候服务器并不需要任何准备,而释放连接时候不同,服务器突然收到释放连接,会有一些必要数据进行处理,所以只能先发送一个确认报文,等数据处理完了,再发送释放报文。

为什么第四次挥手请求发出后,客户端要等待2MSL时间?

原因:客户端想确认服务器是否成功收到第四次挥手的确认报文

MSL即Maximum Segment Lifetime:指的是一段TCP报文在传输过程中的最大生命周期,也是服务器第三次挥手发出的释放报文和客户端第四次挥手发出的确认报文所能保持有效的最大时长。

服务器在第三次挥手后,会等待1MSL,如果没收到客户端的确认报文,就会超时重传。这样子,客户端就会在第四次挥手后的2MSL时间内收到重传的报文,之后客户端重新发出第四次挥手的报文,重新等待2MSL,直到2MSL时间内服务器没有重传,就证明服务器已经收到第四次挥手的报文,关闭连接端口了。