三次握手:客户端为a,服务端为b;开始都是closed状态;a主动打开进入到syn_sent状态,b被动打开进入listen状态;
第一次握手,a向b发送SYN=1,seq为x的包,b收到以后进入syn-rcvd状态;
第二次握手,b向a发送SYN=1,ACK=1,seq=y,ack=x+1的包,a收到后进入eatablished状态;
第三次握手,a向b发送ACK=1,seq=x+1,ack=y+1的包,b收到以后进入established状态。
所以在三次握手阶段:客户端是closed syn-send established 服务端是colsed listen syn-rcvd established
四次挥手:客户端是a,服务端是b,开始都是established状态;a主动关闭,发送FIN=1 seq=u,进入FIN_WAIT_1状态;b收到后,发送ACK=1,seq=v,ack=u+1,进入到close_wait状态;
a收到数据进入到FIN_WAIT_2状态,,接着进行未传送完数据的传送,b发送完数据后,发送FIN=1,seq=w,ack=u+1,进入到last_ack状态;
a收到后进入到time_wait状态,等待两个MSL时间(最大数据报时间),发送ACK=1,seq=u+1,ack=w+1进入到closed状态;
b收到后进入到closed状态。
所以在四次挥手过程中:客户端的状态是established fin_wait_1 fin_wait_2 time_wait closed;服务端的状态是established close_wait last_ack closed
总的状态变化是 客户端:closed—syn_sent——established——fin_wait_1——fin_wait_2——time_wait——closed
服务端是closed——listen——syn_rcvd——eatablished——close_wait——last_ack——closed
问题】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。
只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。