1. 程式人生 > >tcp三次握手建立連線和4次揮手斷開連線

tcp三次握手建立連線和4次揮手斷開連線

  • [LAST_ACK -> CLOSED] 伺服器收到了對FIN的ACK, 徹底關閉連線. 客戶端狀態改變: 1.[CLOSED -> SYN_SENT] 客戶端呼叫connect, 傳送同步報文段; 2.[SYN_SENT -> ESTABLISHED] connect呼叫成功, 則進入ESTABLISHED狀態, 開始接收發送資料; 3.[ESTABLISHED -> FIN_WAIT_1] 客戶端主動呼叫close時, 向伺服器傳送結束報文段, 同時進入 FIN_WAIT_1; 4.[FIN_WAIT_1 -> FIN_WAIT_2] 客戶端收到伺服器對結束報文段的確認, 則進入FIN_WAIT_2, 開始 等待伺服器的結束報文段; 5.[FIN_WAIT_2 -> TIME_WAIT] 客戶端收到伺服器發來的結束報文段, 進⼊入TIME_WAIT, 併發出 LAST_ACK;1 6.[TIME_WAIT -> CLOSED] 客戶端要等待一個2MSL(Max Segment Life, 報文最大生存時間)的時間, 才會進入CLOSED狀態. 接下來看幾個問題: 1.為什麼主動方要等待或者TIME_WAIT狀態有什麼用?並且為什麼是2個MSL時間?
    如果啟動server端,然後啟動client,然後用ctrl+c使程式server終止,緊接著再執行server,結果如下: 在這裡插入圖片描述 為什麼會出現這種錯誤呢? 是因為雖然server程式終止,但是tcp協議的連線並沒有斷開,那麼就不會再監聽同樣的server埠。 TCP協議規定,主動關閉連線的一方要處於TIME_WAIT狀態,等待2個MSL的時間才能回到CLOSED狀態;由於server是主動關閉一方,那麼在TIME_WAIT期間就不能再次監聽同樣的埠; 為什麼會有TIME_WAIT? 1.可靠的終止TCP連線,若處於time_wait的client傳送給server確認報文段丟失的話,server將在此又一次傳送FIN報文段,那麼client必須處於一個可接收的狀態就是time_wait而不是close狀態。 2.保證遲來的TCP報文段有足夠的時間被識別並丟棄,linux 中一個TCPport不能開啟兩次或兩次以上。當client處於time_wait狀態時我們將無法使用此port建立新連線,假設不存在time_wait狀態,新連線可能會收到舊連線的資料。 為什麼TIME_WAIT是 2MSL?
    1. time_wait持續的時間是2MSL,保證舊的資料能夠丟棄。由於網路中的資料最大存在MSL。保證舊的資料丟棄的好處是:保證在兩個傳輸方向上的尚未被接收或遲到大的報文段都已經消失,否則伺服器重啟後可能會收到來自上一個程序的遲到的資料,但這種資料很有可能就是錯誤的。 2.同時也保證最後一個報文可靠到達,假設最後一個ACK丟失,那麼伺服器會重新發送一個FIN包,這時雖然客戶端的程序不在了,但是TCP連線依然在,會重發最後一個ACK。 為什麼建立連線是3次握手,斷開連線是4次揮手? 這是由於TCP的半關閉造成的。因為TCP連線是全雙工的(即資料可在兩個方向上同時傳遞)所以進行關閉時每個方向上都要單獨進行關閉。這個單方向的關閉就叫半關閉。當一方完成它的資料傳送任務,就傳送一個FIN來向另一方通告將要終止這個方向的連線。傳送了FIN只是表示這端不能繼續傳送資料(應用層不能再呼叫send傳送),但是還可以接收資料。收到一個 FIN只意味著這一方向上沒有資料流動,一個TCP連線在收到一個FIN後仍能傳送資料,比如:如主機A收到主機B的FIN斷開TCP連線請求,只是表示主機B已經發送完資料,主機A收到FIN後作出應答,並終止這個方向的資料傳輸,此時處於半關閉狀態。但是主機A仍然可以傳送資料的,只有當主機A傳送完資料併發送FIN給主機B時,主機B才停止這個方向的資料傳輸,並關閉TCP連線。 2)在很多時候,TCP連線的斷開都會由TCP層自動進行,例如當ctrl+c終止你的程式,TCP連線依然會正常關閉。 泛洪攻擊
    SYN泛洪攻擊則是客戶端向伺服器傳送SYN報文之後就不再響應伺服器迴應的報文。由於伺服器在處理TCP請求時,會在協議棧留一塊緩衝區來儲存握手的過程,當然如果超過一定的時間內沒有接收到客戶端的報文,本次連線在協議棧中儲存的資料將會被丟棄。攻擊者如果利用這段時間傳送大量的連線請求,全部掛起在半連線狀態。這樣將不斷消耗伺服器資源,直到拒絕服務。