理解tcp關閉連線中的time wait狀態

2021-09-24 21:18:47 字數 1629 閱讀 4222

首先看一下tcp關閉連線時的四次握手過程:

1.client向server傳送fin包,表示client主動要關閉連線,然後進入fin_wait_1狀態,等待server返回ack包。此後client不能再向server傳送資料,但能讀取資料。

2.server收到fin包後向client傳送ack包,然後進入close_wait狀態,此後server不能再讀取資料,但可以繼續向client傳送資料。

3.client收到server返回的ack包後進入fin_wait_2狀態,等待server傳送fin包。

4.server完成資料的傳送後,將fin包傳送給client,然後進入last_ack狀態,等待client返回ack包,此後server既不能讀取資料,也不能傳送資料。

5.client收到fin包後向server傳送ack包,然後進入time_wait狀態,接著等待足夠長的時間(2msl)以確保server接收到ack包,最後回到closed狀態,釋放網路資源。

6.server收到client返回的ack包後便回到closed狀態,釋放網路資源。

但是有些爬蟲伺服器或者web伺服器為什麼有時候會有大量time_wait狀態出現?

從 上面的示意圖可以看得出來,time_wait是主動關閉連線的一方保持的狀態,在發完最後乙個ack狀態後,發起者的狀態會調整為time_wait。 對於爬蟲伺服器來說他本身就是「客戶端」,在完成乙個爬取任務之後,他就 會發起主動關閉連線,從而進入time_wait的狀態,然後在保持這個狀態2msl(max segment lifetime  /proc/sys/net/ipv4/tcp_fin_timeout)時間之後,徹底關閉**資源。2msl一般是大於30s,小於4分鐘. 最小也要30s,再大就沒啥意義了.  為什麼要這麼做?明明就已經主動關閉連線了為啥還要保持資源一段時間呢?這個是tcp/ip的設計者規定 的,主要出於以下兩個方面的考慮:

2. ack丟失的情況: 在主動關閉方傳送的最後乙個 ack(fin) ,有可能丟失。這時候對方(被動方)會重新發fin, 如果這時主動方處於 closed 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 time_wait 狀態,而不能是 closed 。另外這麼設計time_wait 會定時的**資源,並不會占用很大資源的,除非短時間內接受大量請求或者受到攻擊。

如果接收到rst,也就是tcp連線重置,服務端應用有報錯。 

reset報文傳送場景:

rst的標誌位,這個標識為在如下幾種情況下會被設定。

1.當嘗試和未開放的伺服器端口建立tcp連線時,伺服器tcp將會直接向客戶端傳送reset報文

2.雙方之前已經正常建立了通訊通道,也可能進行過了互動,當某一方在互動的過程中發生了異常,如崩潰等,異常的一方會向對端傳送reset報文,通知對方將連線關閉

3.當收到tcp報文,但是發現該報文不是已建立的tcp連線列表可處理的,則其直接向對端傳送reset報文

4.ack報文丟失,並且超出一定的重傳次數或時間後,會主動向對端傳送reset報文釋放該tcp連線

另外我們做大量api請求時會遇到下面的問題. broken pipe和connection reset by peer  .   這其實也是reset的報錯一種.

關閉tcp連線

luolei localhost sudo netstat a grep ssh tcp 0 0 192.168.1.10 40278 com ssh established unix 2 acc stream listening 7565 tmp ssh uyvolk4882 agent.4882...

關閉TCP連線

從tcp協議角度來看,乙個已建立的tcp連線有兩種關閉方式,一種是正常關閉,即四次揮手關閉連線 還有一種則是異常關閉,我們通常稱之為連線重置 reset 首先說一下正常關閉時四次揮手的狀態變遷,關閉連線的主動方狀態變遷是fin wait 1 fin wait 2 time wait,而關閉連線的被動...

關閉TCP連線的學問

從tcp協議角度來看,乙個已建立的tcp連線有兩種關閉方式,一種是正常關閉,即四次揮手關閉連線 還有一種則是異常關閉,我們通常稱之為連線重置 reset 首先說一下正常關閉時四次揮手的狀態變遷,關閉連線的主動方狀態變遷是fin wait 1 fin wait 2 time wait,而關閉連線的被動...