1 連接狀態圖
2 建立連接:三次握手,不使用DNS和使用DNS
3 關閉連接-四次握手
連接雙方任何一方調用close()
后,連接的兩個傳輸方向都關閉,不能再發送數據了。如果一方調用shutdown()
則連接處於半關閉狀態,仍可接收對方發來的數據。
如果出現半關閉,例如客戶->服務器方向關閉。則服務器還可以發,客戶端還可以收。
協議規定主動關閉一方,進入FIN_WAIT_2
->TIME_WAIT
,必須等待2MSL(MSL為最大報文段生存時間,LWIP為1分鍾,windows為2分鍾)時間然后才進入CLOSED
,刪除TCP控制塊。在2MSL等待時間內遲到的報文段將被拋棄。
如果我們在客戶端關閉一個連接然后又立刻建立連接(使用同一端口號),2MSL時間內之前連接的端口號不能使用,即使調用bind
函數也將返回-1(綁定失敗),內核將自動分配一個新的端口號使用。通常情況下這個我們並不關心,因為客戶端的端口號我們並不關心,只要能用就可以。但是如果是服務器就不一樣了,服務器的端口一般是固定的,客戶端必須知道服務器的端口號才能建立連接,所以如果服務器端主動斷開連接時,就需要注意,或者做一些處理:不讓它等待2MSL后才可以使用,具體做法:使能SO_REUSEPORT
(允許重用本地地址),可以通過調用setsockopt
函數來使能。
2MSL等待的原因:報文段有生存時間,當連接關閉時,有可能收到遲到的報文段。這時,若立馬就建立新的連接(同一端口),那么新的連接就會接收遲到的報文,誤以為是發給自己的。另一個原因是可靠的實現全雙工連接的終止。
在FIN_WAIT_2
狀態我們已經發出了FIN
,並且另一端也已對它進行確認。除非我們在實行半關閉,否則將等待另一端的應用層意識到它已收到一個文件結束符說明,並向我們發一個FIN來關閉另一方向的連接。只有當另一端的進程完成這個關閉,我們這端才會從FIN_WAIT_2
狀態進入TIME_WAIT
狀態。這意味着我們這端可能永遠保持這個狀態(FIN_WAIT_2
,如果對方不發送FIN包)。另一端也將處於CLOSE_WAIT
狀態,並一直保持這個狀態直到應用層決定進行關閉(調用close
然后進入LAST_ACK
)。