[小端日记] - 如何理解TCP的四次挥手


       当客户端和服务器经过三次握手创建了TCP链接之后,当数据传送完毕,确定是要断开TCP链接的啊。那对于TCP的断开链接,这里就有了神秘的“四次挥手”。
前端


第一次挥手:服务器

Client (可使客户端,也能够是服务器端),设置Sequence Number和Acknowledgment Number,向 Server发送一个FIN报文段;此时,Client 进入FIN_WAIT_1状态;这表示 Client 没有数据要发送给 Server了;网络

客户端发送第一次挥手后,就不能在向 服务端发送数据了。前端工程师

第二次挥手:并发

Server 收到了 Client 发送的FIN报文段,向 Client 回一个ACK报文段,Acknowledgment Number 为 Sequence Number 加 1;Client 进入 FIN_WAIT_2 状态;Server 告诉 Client ,我“赞成”你的关闭请求;cdn

Server 第一次响应后,还能够继续向 Client 发送数据,这里只是告诉 Client ,我收到你发送的关闭请求。blog

第三次挥手资源

Server 向 Client 发送 FIN 报文段,请求关闭链接,同时 Server 进入 CLOSE_WAIT 状态;同步

当 Server 的数据响应完成后,再告诉 Client,我这边也能够关闭请求了, 这时
Server 就不能再向 Client 发送数据了
it

第四次挥手

Client 收到 Server 发送的 FIN 报文段,向 Server 发送 ACK 报文段,而后 Client 进入
TIME_WAIT 状态;Server 收到 Client 的 ACK 报文段之后,就关闭链接;此时,Client
等待2MSL后依然没有收到回复,则证实 Server 端已正常关闭,那好,Client 也能够关闭链接了。


问:为何链接的时候是三次握手,关闭的时候倒是四次握手? 

答:由于当Server端收到Client端的SYN链接请求报文后,能够直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。可是关闭链接时,当Server端收到FIN报文时,极可能并不会当即关闭SOCKET,因此只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端全部的报文都发送完了,我才能发送FIN报文,所以不能一块儿发送。故须要四步握手。  

问:为何TIME_WAIT状态须要通过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,咱们能够直接进入CLOSE状态了,可是咱们必须假象网络是不可靠的,有能够最后一个ACK丢失。因此TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server若是没有收到ACK,将不断重复发送FIN片断。因此Client不能当即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK以后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。若是在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片断在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。若是直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP链接。  

问:为何不能用两次握手进行链接?  

答:3次握手完成两个重要的功能,既要双方作好发送数据的准备工做(双方都知道彼此已准备好),也要容许双方就初始序列号进行协商,这个序列号在握手过程当中被发送和确认。 如今把三次握手改为仅须要两次握手,死锁是可能发生的。做为例子,考虑计算机S和C之间的通讯,假定C给S发送一个链接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为链接已经成功地创建了,能够开始发送数据分组。但是,C在S的应答分组在传输中被丢失的状况下,将不知道S 是否已准备好,不知道S创建什么样的序列号,C甚至怀疑S是否收到本身的链接请求分组。在这种状况下,C认为链接还未创建成功,将忽略S发来的任何数据分 组,只等待链接确认应答分组。而S在发出的分组超时后,重复发送一样的分组。这样就造成了死锁。 

问:若是已经创建了链接,可是客户端忽然出现故障了怎么办?  

TCP还设有一个保活计时器,显然,客户端若是出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会从新复位这个计时器,时间一般是设置为2小时,若两小时尚未收到客户端的任何数据,服务器就会发送一个探测报文段,之后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭链接。 


结束语: 作一个努力、勤奋、主动的前端工程师

相关文章
相关标签/搜索