一、TCP 協議
1、概念:TCP協議,即 傳輸控制協議。它是面向連接、可靠的傳輸層協議。
2、特點:工作在 傳輸層;每一條TCP連接只能是點對點的;面向連接、可靠性;提供全雙工通信;基於字節流。
3、TCP 數據報格式: TCP 基於 字節流
源端口號、目的端口號:各佔 2字節(16位) 序號:4字節 範圍[0,2^32 - 1],使用mod/(2^32)計算
URG:緊急 1 緊急指針字段有效 ACK:確認 1 確認字段有效
PSH:推送 兩應用進行交互,一方希望發送命令後就立即收到對方響應
RST:復位 (重建位/重置位) 1 TCP連接出現嚴重錯誤,須釋放連接,再重新建立連接
SYN:同步 1 連接請求/連接接受報文
FIN:終止 1 數據已發送完畢,釋放連接
窗口字段:現在允許對方發送的數據量
檢驗和:2字節 範圍[首部 + 數據]
緊急指針:2字節 (僅在URG=1時有意義)指出緊急數據的末尾在文段中的位置
MSS:最大報文長度 [TCP報文長度 - TCP首部長度]
選項:長度可變(最長40字節) 若無選項,則 TCP首部長度 20字節
3、連接: 套接字socket = (IP地址 :端口號)
I. 三次握手: 建立連接的過程:
1.客戶端發出段1,SYN位表示連接請求。
序號是1000,這個序號在網絡通訊中用作臨時的地址,每發一個數據字節,這個序號要加1,這樣在接收端可以根據序號排出數據包的正確順序,也可以發現丟包的情況。另外,規定SYN位和FIN位也要佔一個序號,這次雖然沒發數據,但是由於發了SYN位,因此下次再發送應該用序號1001。mss表示最大段尺寸,如果一個段太大,封裝成幀後超過了鏈路層的最大幀長度,就必須在IP 層分片,爲了避免這種情況,客戶端聲明自己的最大段尺寸,建議服務器端發來的段不要超過這個長度。
2.服務器發出段2,也帶有SYN位,同時置ACK位表示確認,確認序號是1001,表示“我接收到序號1000及其以前所有的段,請你下次發送序號爲1001的段”,也就是應答了客戶端的連接請求,同時也給客戶端發出一個連接請求,同時聲明最大尺寸爲1024。
3.客戶端發出段3,對服務器的連接請求進行應答,確認序號是8001。
II. 四次握手: 關閉連接的過程:
1. 客戶端發出段7, FIN位:關閉連接的請求。
2. 服務器發出段8, 應答客戶端的關閉連接請求。
3. 服務器發出段9, 其中也包含FIN位,向客戶端發送關閉連接請求。
4. 客戶端發出段10, 應答服務器的關閉連接請求。
注:正在關閉或者TIME_WAIT狀態的tcp連接,不能傳輸http請求和響應。
III.TIME_WAIT
通信雙方建立TCP連接後,主動關閉連接的一方就會進入TIME_WAIT狀態。
客戶端主動關閉連接時,會發送最後一個ack後,然後會進入TIME_WAIT狀態,再停留2個MSL時間(後有MSL的解釋),進入CLOSED狀態。
MSL就是maximum segment lifetime(最大分節生命期),這是一個IP數據包能在互聯網上生存的最長時間,超過這個時間IP數據包將在網絡中消失 。MSL在RFC 1122上建議是2分鐘,而源自berkeley的TCP實現傳統上使用30秒。
TIME_WAIT狀態維持時間: 兩個MSL時間長度,也就是在1-4分鐘。Windows操作系統就是4分鐘。
1)客戶端主動關閉連接
[ 進入TIME_WAIT狀態的一般情況下是客戶端 ]
大多數服務器端一般執行被動關閉,服務器不會進入TIME_WAIT狀態。
當在服務器端關閉某個服務再重新啓動時,服務器是會進入TIME_WAIT狀態的。
舉例:
1.客戶端連接服務器的80服務,這時客戶端會啓用一個本地的端口訪問服務器的80,訪問完成後關閉此連接,立刻再次訪問服務器的
80,這時客戶端會啓用另一個本地的端口,而不是剛纔使用的那個本地端口。原因就是剛纔的那個連接還處於TIME_WAIT狀態。
2.客戶端連接服務器的80服務,這時服務器關閉80端口,立即再次重啓80端口的服務,這時可能不會成功啓動,原因也是服務器的連接還處於TIME_WAIT狀態。
服務端提供服務時,一般監聽一個端口就夠了。例如Apach監聽80端口。
客戶端則是使用一個本地的空閒端口(大於1024),與服務端的Apache的80端口建立連接。
當通信時使用短連接,並由客戶端主動關閉連接時,主動關閉連接的客戶端會產生TIME_WAIT狀態的連接,一個TIME_WAIT狀態的連接就佔用了一個本地端口。這樣在TIME_WAIT狀態結束之前,本地最多就能承受6萬個TIME_WAIT狀態的連接,就無端口可用了。
客戶端與服務端進行短連接的TCP通信,如果在同一臺機器上進行壓力測試模擬上萬的客戶請求,並且循環與服務端進行短連接通信,那麼這臺機器將產生4000個左右的TIME_WAIT socket,後續的短連接就會產生address already in use : connect的異常。
關閉的時候使用RST的方式,不進入 TIME_WAIT狀態,是否可行?
2)服務端主動關閉連接
[ 大多數服務器端一般執行被動關閉,服務器不會進入TIME_WAIT狀態 ]
服務端提供在服務時,一般監聽一個端口就夠了。例如Apach監聽80端口。
客戶端則是使用一個本地的空閒端口(大於1024),與服務端的Apache的80端口建立連接。
當通信時使用短連接,並由服務端主動關閉連接時,主動關閉連接的服務端會產生TIME_WAIT狀態的連接。
由於都連接到服務端80端口,服務端的TIME_WAIT狀態的連接會有很多個。
服務器端爲了解決這個TIME_WAIT問題,可選擇的方式有三種:
保證由客戶端主動發起關閉(即做爲B端)
關閉的時候使用RST的方式
對處於TIME_WAIT狀態的TCP允許重用
3)使用情形
返回結果如下:
LAST_ACK 14
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18122
對上述結果的解釋:
CLOSED:無連接是活動的或正在進行
LISTEN:服務器在等待進入呼叫
SYN_RECV:一個連接請求已經到達,等待確認
SYN_SENT:應用已經開始,打開一個連接
ESTABLISHED:正常數據傳輸狀態
FIN_WAIT1:應用說它已經完成
FIN_WAIT2:另一邊已同意釋放
ITMED_WAIT:等待所有分組死掉
CLOSING:兩邊同時嘗試關閉
TIME_WAIT:另一邊已初始化一個釋放
LAST_ACK:等待所有分組死掉