1. 程式人生 > >TCP握手協議-原理和案例(服務端大量CLOSE_WAIT,TIME_WAIT問題)參考總結

TCP握手協議-原理和案例(服務端大量CLOSE_WAIT,TIME_WAIT問題)參考總結

網際網路公司,對網路通訊原理的掌握估計要求比較高,分分鐘面試官第一個問題問你就是請描述一下TCP握手協議,為什麼有3次握手和4次握手的區別。

如果要深入而且全面的理解這個協議,建議瀏覽相關專業書籍,例如《UNIX 網路程式設計》。本部落格定位是讓有這個基礎概念的小白同學加深一下理解。

題外話,之所以寫起這篇部落格,源於週末約了一個勤奮加班的同學聚會,去了他的公司,恰好他遇到伺服器上發現有大量埠處於CLOSE_WAIT狀態的問題。於是回去後我就搜了相關資料,藉此機會做個總結,也分享一下別人很好的案例。

先來上個原理簡圖:

這裡寫圖片描述

上圖描述分兩個部分,
第一部分是客戶端主動請求連線的過程。
第二部分是客戶端主動請求關閉連線的過程。

  • 三次握手例子通俗描述:
打電話的例子:
A : 你好我是A,你聽得到我在說話嗎
B : 聽到了,我是B,你聽到我在說話嗎
A : 嗯,聽到了
建立連線,開始聊天!
  • 四次握手例子通俗描述:
A:“喂,我不說了。”A->FIN_WAIT1
B:“我知道了。等下,上一句還沒說完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2
B:”好了,說完了,我也不說了。”B->LAST_ACK
A:”我知道了。”A->TIME_WAIT | B->CLOSED
A等待2MSL,保證B收到了訊息,否則重說一次”我知道了”,A
->CLOSED

問題一,3次握手協議和4次握手協議的區別是什麼?

可以看出,TCP之所以被稱為可靠傳輸協議,就是靠握手協議保證資料傳輸,通俗一點說,就是當你傳送訊號給對方,如何確保對方真的收到你的訊號。而3次握手和4次握手的區別在於,3次握手是發生在請求連線的過程,4次握手是發生在關閉連線的過程。之所以關閉連線過程多了1個步驟,是因為被動關閉連線的一方在被關閉連線時候還處於傳送資料未完成狀態。如上圖的下半部分ack M+1 不能和Fin N同時傳送。ack M+1就是告訴對方“哦,我知道你要關閉了”,之後的 Fin才是告訴對方“我的資料也已經發送完畢了”。

問題二,傳送方如何知道接收方究竟有沒有收到呢?

繼續深度思考,整個握手協議是為了讓傳送方確保接收方收到資訊,那麼上圖下半部分最後一個步驟ack N+1傳送出去後,傳送方(客戶端)如何知道接收方(服務端)究竟有沒有收到呢?握手協議的設計魅力就體現出來了,這裡涉及一個2MSL的概念。傳送方(客戶端)的邏輯是這樣思考的,給接收方一個時間,在這個時間段內,假如接收方收不到資訊,則接收方肯定會不斷髮送Fin N訊號過來。換言之,如果接收方收到傳送方(客戶端)的確認資訊,則在這個時間段內,傳送方(客戶端)不會收到接收方重複發過來的Fin N訊號。而這個所謂的時間段,就被定義為兩倍的MSL(Maximum Segment Lifetime)。

至此,有了上述基本的理解後,可以進入實戰階段了。

伺服器發現大量CLOSE_WAIT狀態的埠

案例原因總結:資料庫連線問題導致伺服器端執行緒阻塞,伺服器執行緒阻塞導致伺服器socket不能正常關閉。

案例原因總結:伺服器端的socket程式設計程式關閉socket方式不正確,導致伺服器socket沒有徹底關閉。

解決方案:都是修改程式保證程式處理正常,關閉socket正常。

謹記,CLOSE_WAIT狀態的一端都是被動關閉連線的,如果該端的socket程式沒有正確關閉從而傳送不了FIN訊號,將會導致長時間CLOSE_WAIT狀態。

伺服器發現大量TIME_WAIT狀態的埠

案例原因總結:通常這種情況發生在大量高併發短連線的應用場景,本身程式沒什麼錯。出現這種大量TIME_WAIT狀態源於主動關閉連線的一方(例如服務端)在2MSL等待時間裡,有大量的高併發連線需要開啟新的socket埠,而因為2MSL時間(例如2分鐘)相比這些短連線處理完業務的時間(例如2秒鐘)長,所以顯得TIME_WAIT的socket時間佔用過長。

解決方案:分多臺伺服器分擔高併發連線請求。

另外,再繼續深入拓展,上文對於握手協議的各個狀態過程,並沒有提及超時處理情形,可以想象,假如有大量CLOSE_WAIT埠,難道伺服器沒有保障措施自動處理這些問題?答案是有的,伺服器有可能有個預設時間(這個時間可能預設很久),就是CLOSE_WAIT的埠多長時間沒有反應就自動CLOSE的處理。同樣,TIME_WAIT狀態超時處理就是2MSL。當然,不同的系統對於這個異常處理的機制可能都不一樣,要具體情況再看。