TCP運作方式
TCP協定的執行可劃分為三個階段:連接建立(connection establishment)、資料傳送(data transfer)和連接終止(connection termination)。
連接建立
TCP用三路握手(或稱三次握手,three-way handshake)過程建立一個連接。在連接建立過程中,很多參數要被初始化,例如序號被初始化以保證按序傳輸和連接的強壯性。
資料傳送
主機收到一個TCP包時,用兩端的IP位址與埠號來標識這個TCP包屬於哪個session。在TCP的資料傳送狀態,很多重要的機制保證了TCP的可靠性和強壯性。
連接終止
連接終止使用了四路握手過程(或稱四次握手,four-way handshake),在這個過程中連接的每一側都獨立地被終止。當一個端點要停止它這一側的連接,就向對側傳送FIN,對側回覆ACK表示確認。因此,拆掉一側的連接過程需要一對FIN和ACK,分別由兩側端點發出。
狀態編碼
下表為TCP狀態碼列表,以S指代伺服器,C指代客戶端,S&C表示兩者,S/C表示兩者之一:[15]
LISTEN S
:伺服器等待從任意遠端TCP埠的連接請求。偵聽狀態。SYN-SENT C
:客戶在傳送連接請求後等待匹配的連接請求。通過connect()函式向伺服器發出一個同步(SYNC)訊號後進入此狀態。SYN-RECEIVED S
:伺服器已經收到並行送同步(SYNC)訊號之後等待確認(ACK)請求。ESTABLISHED S&C
:伺服器與客戶的連接已經開啟,收到的資料可以傳送給用戶。資料傳輸步驟的正常情況。此時連接兩端是平等的。這稱作全連接。FIN-WAIT-1 S&C
:(伺服器或客戶)主動關閉端呼叫close()函式發出FIN請求包,表示本方的資料傳送全部結束,等待TCP連接另一端的ACK確認包或FIN&ACK請求包。FIN-WAIT-2 S&C
:主動關閉端在FIN-WAIT-1狀態下收到ACK確認包,進入等待遠端TCP的連接終止請求的半關閉狀態。這時可以接收資料,但不再傳送資料。- C
LOSE-WAIT S&C
:被動關閉端接到FIN後,就發出ACK以回應FIN請求,並進入等待本地用戶的連接終止請求的半關閉狀態。這時可以傳送資料,但不再接收資料。 CLOSING S&C
:在發出FIN後,又收到對方發來的FIN後,進入等待對方對己方的連接終止(FIN)的確認(ACK)的狀態。少見。LAST-ACK S&C
:被動關閉端全部資料傳送完成之後,向主動關閉端傳送FIN,進入等待確認包的狀態。TIME-WAIT S/C
:主動關閉端接收到FIN後,就傳送ACK包,等待足夠時間以確保被動關閉端收到了終止請求的確認包。【按照RFC 793,一個連接可以在TIME-WAIT保證最大四分鐘,即最大分段壽命(maximum segment lifetime)的2倍】CLOSED S&C
:完全沒有連接。
系統存在過多TIME_WAIT狀態的連線
根據TCP協議定義的3次握手斷開連接規定,發起socket主動關閉的一方socket將進入TIME_WAIT狀態,TIME_WAIT狀態將持續2個MSL(Max Segment Lifetime),在Windows下默認為4分鐘,即240秒, TIME_WAIT狀態下的socket不能被回收使用.具體現像是對於一個處理大量短連接的服務器,如果是由服務器主動關閉客戶端的連接,將導致服務器端存在大量的處於TIME_WAIT狀態的socket,甚至比處於Established狀態下的socket多的多,嚴重影響服務器的處理能力,甚至耗盡可用的socket,停止服務.
這邊有相關文章探討此問題:
谈谈 TCP 的 TIME_WAIT
TCP TIME_WAIT的釋義
簡而言之,暫時解決的方式是縮短系統預設TIME_WAIT的時間。以長時間來講,則應該檢查程式是否有不正常未將連線正常關閉的狀況,以修改程式來避免此狀況才是根本之道。