一 TCP四次挥手原理及抓包情况
TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作,如图1所示。
图1 四次挥手原理图
第一次挥手:主动方发送一个FIN,用来关闭主动方到被动方的数据传送;
第二次挥手:被动方收到这个FIN,它发回一个ACK,确认序号为收到的序号加1,和SYN一样,一个FIN将占用一个序号;
第三次挥手:被动方关闭与主动方的连接,发送一个FIN给主动方;
第四次挥手:主动方发回ACK报文确认,并将确认序号设置为收到序号加1;被动方关闭连接
通俗说就是
主动方对被动方说:我不爱你了,咱们离婚吧!--------------->(FIN_WAIT_1状态,等待回应) 被动方回应:那离婚吧,把你的东西都拿走! --------------->(FIN_WAIT_2状态,在关闭连接前将最后一点数据传完) 被动方又说:咱们来个Kiss Goodbye吧! --------------->( LAST_ACK,关闭连接,并请求最后一次确认)
主动方回应:波儿~ --------------> (CLOSED,完毕)
图2 WIRESHARK抓包情况
二 思考题
2.1 、为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。如图3所示:
图3 四次握手的关键点
2.2、为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。