tcp是全雙工通道,通訊雙方均可以獨立關閉本身的通訊通道,也就是半關閉。服務器
client先發送FIN告知對方我已經完成數據發送了,server回覆ack來肯定我知道了。這樣一個流程,就關閉了client的發送信息通道。可是還能夠接收來自server方的數據。socket
server此時已經知道接收不到client的數據了,可是還能夠給它發送數據。若是server也沒有啥數據要發送給對方了,server也會以FIN標誌位發送一個信息給client,client接到後,也會傳遞一個ack表示知道了。這樣子,雙方都完成了關閉。
tcp
客戶端數據發送完成,則它向服務端發送鏈接釋放請求。該請求只有報文頭,頭中攜帶的主要參數爲:FIN=1,seq=u。此時,客戶端將進入FIN-WAIT-1狀態。TCP規定,FIN報文段即便不攜帶數據,也要消耗一個序號。線程
服務器收到客戶端鏈接釋放報文,通知相應的高層應用進程,告訴它客戶端向服務器這個方向的鏈接已經釋放了。此時服務端進入了CLOSE-WAIT(關閉等待)狀態,並向客戶端發出鏈接釋放的應答,其報文頭包含:ACK=1,ack=u+1,seq=v。客戶端收到該應答後,進入FIN-WAIT-2狀態,等待服務器發送鏈接釋放報文(在這以前還須要接受服務器發送的最後的數據)。第二次揮手完成後,客戶端到服務端方向的鏈接已經釋放,服務端不會再接收客戶端的數據,客戶端也沒有數據要發送了。但服務端到客戶端方向的鏈接仍然存在,服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。server
服務端將最後的數據發送完畢後,就向客戶端發送鏈接釋放報文,其報文頭包含:FIN=1,ack=u+1,因爲在CLOS-WAIT狀態,服務端極可能又發送了一些數據,假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。blog
客戶端收到服務器的鏈接釋放報文後,向服務端發出確認應答,報文頭:ACK=1,ack=w+1,seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。該狀態會持續2MSL(最長報文段壽命)時間,這個期間TCP鏈接還未釋放,若該時間段內沒有服務端的重發請求的話,客戶端就進入CLOSED狀態,服務端只要收到了客戶端發出的確認,當即進入CLOSED狀態。就結束了此次的TCP鏈接。能夠看到,服務器結束TCP鏈接的時間要比客戶端早一些。進程
client已經關閉了socket鏈接,而我方忙於讀或寫,沒有及時的去關閉鏈接。資源