TCP連接建立與斷開

七層協議

其中TCP處理transport層,主要是用來建立可靠的連接。 而建立連接的基礎,是他豐富的報文內容(md~超級多).我們先來解釋一下。 首先,我們TCP3次握手用的報文就是綠色的"TCP Flags"內容。 通過發送ACK,SYN包實現。具體涉及的Tag詳見:

  • Source Port / Destination Port:這個就是客戶端口(源端口)和服務器端口(目的端口). 端口就是用來區別主機中的不同進程,通過結合源IP和目的IP結合,得出唯一的TCP連接。
  • Sequence Number(seqNumber): 一般由 客戶端發送,用來表示報文段中第一個數據字節在數據流中的序號,主要用來解決網絡包亂序的問題。
  • Acknowledgment Number(ACK): 即就是用來存放客戶端發來的seqNumber的下一個信號(seqNumber+1). 只有當 TCP flags中的ACK為1時才有效. 主要是用來解決不丟包的問題。
  • TCP flags: TCP中有6個首部,用來控制TCP連接的狀態.取值為0,1.這6個有:URG,ACK,PSH,RST,SYN,FIN.
    • URG 當為1時,用來保證TCP連接不被中斷, 并且將該次TCP內容數據的緊急程度提升(就是告訴電腦,你丫趕快把這個給resolve了)
    • ACK 通常是服務器端返回的。 用來表示應答是否有效。 1為有效,0為無效
    • PSH 表示,當數據包得到后,立馬給應用程序使用(PUSH到最頂端)
    • RST 用來確保TCP連接的安全。 該flag用來表示 一個連接復位的請求。 如果發生錯誤連接,則reset一次,重新連。當然也可以用來拒絕非法數據包。
    • SYN 同步的意思,通常是由客戶端發送,用來建立連接的。第一次握手時: SYN:1 , ACK:0. 第二次握手時: SYN:1 ACK:1
    • FIN 用來表示是否結束該次TCP連接。 通常當你的數據發送完后,會自動帶上FIN 然后斷開連接

TCP 3次握手

網絡傳輸示意圖
  • 第一次握手. 客戶端向服務器發送一個SYN包,并且添加上seqNumber(假設為x),然后進入SYN_SEND狀態,并且等待服務器的確認。
  • 第二次握手: 服務器接受SYN包,并且進行確認,如果該請求有效,則將TCP flags中的ACK 標志位置1, 然后將AckNumber置為(seqNumber+1),并且再添加上自己的seqNumber(y), 完成后,返回給客戶端.服務器進入SYN_RECV狀態.(這里服務端是發送SYN+ACK包)
  • 第三次握手 客戶端接受ACK+SYN報文后,獲取到服務器發送AckNumber(y), 并且 將新頭部的AckNumber變為(y+1).然后發送給服務器,完成TCP3次連接。此時服務器和客戶端都進入ESTABLISHED狀態.

假如是2次的話, 可能會出現這樣一個情況。

  • 當客戶端發送一次請求A后,但是A在網絡延遲了很久, 接著客戶端又發送了一次B,但是此時A已經無效了。 接著服務器相應了B,并返回TCP連接頭,建立連接(這里就2次哈)。 然后,A 歷經千山萬水終于到服務器了, 服務器一看有請求來了,則接受,由于一開始A帶著的TCP格式都是正確的,那么服務器,理所應當的也返回成功連接的flag,但是,此時客戶端已經判斷該次請求無效,廢棄了。 然后服務器,就這么一直掛著(浪費資源),造成的一個問題是,md, 這個鍋是誰的? 所以,為了保險起見,再補充一次連接就可以了。所以3次是最合適的。在Chinese中,以3為起稱為多,如果你用4,5,6,7,8...次的話,這不更浪費嗎?

TCP4次揮手

四次揮手
  • 第一次揮手: A機感覺此時如果keep-alive比較浪費資源,則他提出了分手的請求。設置SeqNumber和AckNumber之后,向B機發送FIN包, 表示我這已經沒有數據給你了。然后A機進入FIN_WAIT_1狀態
  • 第二次揮手:B機收到了A機的FIN包,已經知道了A機沒有數據再發送了。此時B機會給A機發送一個ACK包,并且將AckNumber 變為 A機傳輸來的SeqNumber+1. 當A機接受到之后,則變為FIN_WAIT_2狀態。表示已經得到B機的許可,可以進行關閉操作。不過此時,B機還是可以向A機發送請求的。
  • 第三次揮手 B機向A機發送FIN包,請求關閉,相當于告訴A機,我這里也沒有你要的數據了。然后B機進入CLOSE_WAIT狀態.(這里還需要帶上SeqNumber,大家看圖說話就可以了)
  • 第四次揮手 A機接收到B機的FIN包之后,然后同樣,發送一個ACK包給B機。 B機接受到之后,就斷開了。 而A機 會等待2MSL之后,如果沒有回復,確保服務器端確實是關閉了。然后A機也可以關閉連接。A,B都進入了CLOSE狀態.

2MSL=2*MSL. 而MSL其實就是Maximum Segment Lifetime,中文意思就是報文最大生存時間。RFC 793中規定MSL為2分鐘,實際應用中常用的是30秒,1分鐘和2分鐘等。 同樣上面的TIME_WAT狀態其實也就是2MSL狀態。 如果超過改時間,則會將該報文廢棄,然后直接進入CLOSED狀態.

常見瓶頸
TCP網絡應用出問題,十有八九是以下兩種情況:

  • 主動關閉連接方出現大量TIME_WAIT狀態。

  • 被動關閉連接方出現大量CLOSE_WAIT狀態

  • 主動關閉方在關閉連接后,需要發送ACK,假設ACK丟失了,被動關閉一方會重發它的FIN。主動關閉方必須維持一個有效狀態信息(TIMEWAIT狀態下維持),以便能夠重發ACK。如果主動關閉的socket不維持這種狀態而進入CLOSED狀態,那么主動關閉的socket在處于CLOSED狀態時,接收到FIN后將會響應一個RST。被動關閉一方接收到RST后會認為出錯了。這就是為什么socket在關閉后,仍然處于TIME_WAIT狀態的第一個原因,因為它要等待以便重發ACK。第二個原因是確保連接復用時沒有殘存的數據。TCP不允許新連接復用TIME_WAIT狀態下的socket。處于TIME_WAIT狀態的socket在等待兩倍的MSL時間以后,將會轉變為CLOSED狀態,此時通道內不會存在殘存數據。
    應用程序無法解決TIME_WAIT問題,我想了一個甩鍋的辦法是讓客戶端斷開連接,因為誰主動斷開誰面臨TIMEWAIT。

  • CLOSE_WAIT需要重點關注。被動關閉方在發送ACK以后會處于CLOSE_WAIT狀態,此時只要調用close方法就會發送FIN包,脫離CLOSE_WAIT狀態。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 18.1 引言 TCP是一個面向連接的協議。無論哪一方向另一方發送數據之前,都必須先在雙方之間建立一條連接。本章將...
    張芳濤閱讀 3,427評論 0 13
  • 1、TCP狀態linux查看tcp的狀態命令:1)、netstat -nat 查看TCP各個狀態的數量2)、lso...
    北辰青閱讀 9,509評論 0 11
  • 個人認為,Goodboy1881先生的TCP /IP 協議詳解學習博客系列博客是一部非常精彩的學習筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,092評論 0 8
  • 1.這篇文章不是本人原創的,只是個人為了對這部分知識做一個整理和系統的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,134評論 6 174
  • 今天特叔給大家整理下一篇關于網絡互助保障平臺“眾托幫”的第三季度運營報告。該報告以圖文方式回顧了“眾托幫”自上線以...
    互助特報閱讀 222評論 0 0