TCP 连接的前世今生
前言
大家好!我是盼盼!
之前寫了幾篇關(guān)于算法和 linux 命令的文章,今天來學習下,網(wǎng)絡(luò)協(xié)議相關(guān)的知識。不管你是客戶端,還是服務端開發(fā),網(wǎng)絡(luò)協(xié)議這塊都是要學習和了解的。
工作和面試中,網(wǎng)絡(luò)協(xié)議都會用到。雖然學習網(wǎng)絡(luò)對編碼沒有實質(zhì)的幫助,但對你處理一下網(wǎng)絡(luò)連接問題,幫助大大的。下面來一起學習下,發(fā)車!
緣起
在世界上各地,各種各樣的電腦,運行著各自不同的操作系統(tǒng)為大家服務。這些電腦,在表達同一種信息的時候,所使用的方法是千差萬別。
計算機使用者意識到,計算機只是單兵作戰(zhàn),并不會發(fā)揮太大的作用。只有把它們聯(lián)合起來,電腦才會發(fā)揮出它最大的潛力。
于是人們就想方設(shè)法的,用電線把電腦連接到了一起。但是簡單的連到一起是遠遠不夠的,就好像語言不同的兩個人互相見了面,完全不能交流信息。因而他們需要定義一些共通的東西來進行交流,TCP/IP 就是為此而生。
TCP/IP 不是一個協(xié)議,而是一個協(xié)議族的統(tǒng)稱。里面包括了 IP 協(xié)議,IMCP 協(xié)議,TCP 協(xié)議,以及我們更加熟悉的 http、ftp 協(xié)議等等。電腦有了這些,就好像學會了外語一樣,就可以和其他的計算機終端做自由的交流了。今天我們學習 TCP 協(xié)議。
什么是TCP
TCP(傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,它完成第四層傳輸層所指定的功能,網(wǎng)絡(luò)模型下面介紹。
TCP 協(xié)議的特點是:
-
面向連接:一定是「一對一」才能連接,不能像 UDP 協(xié)議可以一個主機同時向多個主機發(fā)送消息,也就是一對多是無法做到的。
-
可靠交付:無論的網(wǎng)絡(luò)鏈路中出現(xiàn)了怎樣的鏈路變化,TCP 都可以保證一個報文一定能夠到達接收端。
-
面向字節(jié)流:也就是說僅僅把上層協(xié)議傳遞過來的數(shù)據(jù)當成字節(jié)傳輸。
網(wǎng)絡(luò)模型
七層模型
國際標準化組織 ISO ,在1981 年正式推薦了一個網(wǎng)絡(luò)系統(tǒng)結(jié)構(gòu)一七層參考模型,也叫作開放系統(tǒng)互連模。由于這個標準模型的建立,使得各種計算機網(wǎng)絡(luò)均向它靠攏,大大推動了網(wǎng)絡(luò)通信的發(fā)展。
這個 ISO 層網(wǎng)絡(luò)模型各層的名字、主要功能對應的典型設(shè)備和傳輸單位如下圖:
這個七層網(wǎng)絡(luò)模型在數(shù)據(jù)的傳輸過程中還會對數(shù)據(jù)進行封裝,如下圖:
ISO 層網(wǎng)絡(luò)模型中,當一臺主需要傳送用戶的數(shù)據(jù) (data) 時,數(shù)據(jù)首先通過應用層的接口進入應用層。
先看幾個常見報頭術(shù)語簡寫:
-
應用層報頭:Ppplication Header, 簡稱?AH。
-
表示層報頭:Presentation Header, 簡稱?PH。
-
會話層報頭:Session Header, 簡稱?SH。
-
傳輸層報頭:Transport Header, 簡稱?TH。
-
網(wǎng)絡(luò)層報頭:Network Header, 簡稱?NH。
-
數(shù)據(jù)鏈路層報頭:Data link Header, 簡稱?DH。
-
應用層協(xié)議數(shù)據(jù)單元:Protocol Data Unit,簡稱PDU。
-
數(shù)據(jù)鏈路層報尾:Data link Termination,簡稱DT。
在應用層,用戶的數(shù)據(jù)被加上應用層的報頭 AH,形成應用層協(xié)議數(shù)據(jù)單元 PDU,然后被遞交到下層表示層。
表示層并不關(guān)心上層應用層的數(shù)據(jù)格式,而是把整個應用層遞交的數(shù)據(jù)包,看成是一個整體進行封裝,即加上表示層的報頭 PH。然后,遞交到下層會話層。
同樣,會話層、傳輸層、網(wǎng)絡(luò)層(假設(shè)用 TCP 傳輸,則是 TCP 數(shù)據(jù)+ IP 包頭)、數(shù)據(jù)鏈路層(把上層的 TCP 數(shù)據(jù)+ IP 頭統(tǒng)一稱為幀數(shù)據(jù),即幀 +幀數(shù)據(jù)+幀尾(CRC)也都要分別給上層遞交下來的數(shù)據(jù)加上自己的報頭)。
它們是:會話層報頭 SH、傳輸層報頭 TH、網(wǎng)絡(luò)層報頭 NH 和數(shù)據(jù)鏈路層報頭DH。其中,數(shù)據(jù)鏈路層還要給網(wǎng)絡(luò)層遞交的數(shù)據(jù)加上數(shù)據(jù)鏈路層報尾形成最終的一幀數(shù)據(jù)。
當一幀數(shù)據(jù),通過物理層傳送到目標主機的物理層時,該主機的物理層把它遞交到上層一一數(shù)據(jù)鏈路層。數(shù)據(jù)鏈路層負責去掉數(shù)據(jù)幀的幀頭部和尾部(同時還進行數(shù)據(jù)校驗)。如果數(shù)據(jù)沒有出錯,則遞交到上層網(wǎng)絡(luò)層。
同樣,網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應用層也要做類似的工作。最終 ,原始數(shù)據(jù)被遞交到目標主機的具體應用程序中。
五層網(wǎng)絡(luò)模型
五層模型的網(wǎng)絡(luò)體系也經(jīng)常被提到,這五層的名字與功能分別如下所述:
-
應用層:確定進程之間通信的性質(zhì),以滿足用戶需求。應用層協(xié)議有很多。如支持萬維網(wǎng)應用的 HTTP 協(xié)議、支持電子郵件的 SMTP 協(xié)議、等等。
-
傳輸層:負責主機間不同進程的通信。這一層中的協(xié)議有面向連接的 TCP (傳輸控制協(xié)議)、無連接的 UDP (用戶數(shù)據(jù)報協(xié)議);數(shù)據(jù)傳輸?shù)膯挝环Q為報文段或用戶數(shù)據(jù)報。
-
網(wǎng)絡(luò)層:負責分組交換網(wǎng)中不同主機間的通信。作用為:發(fā)送數(shù)據(jù)時,將運輸層中的報文段或用戶數(shù)據(jù)報封裝成 IP 數(shù)據(jù)報,并選擇合適路由。
-
數(shù)據(jù)鏈路層:負責將網(wǎng)絡(luò)層的 IP 數(shù)據(jù)報組裝成幀。
-
物理層?:透明地傳輸比特流。
四層網(wǎng)絡(luò)模型
前面的兩種模型都是學術(shù)上的概念,使用并不廣泛 還有一個四層模型,使用最為廣泛一 TCP/IP 分層模型。幾種模型如下圖:
TCP/IP 分層的四模型的個協(xié)議層分別完成以下的功能:
-
網(wǎng)絡(luò)接口層:包括用于協(xié)作 IP 數(shù)據(jù),在已有網(wǎng)絡(luò)介質(zhì)上傳輸?shù)膮f(xié)議。實際上 TCP/IP 標準并不定義與 ISO 數(shù)據(jù)鏈路層和物理層相對應的功能 。相反,它定義了像 ARP (地址解析協(xié)議)這樣的協(xié)議,提供 TCP/IP 協(xié)議的數(shù)據(jù)結(jié)構(gòu)和實際物理硬件之間的接口。
-
網(wǎng)絡(luò)層:網(wǎng)絡(luò)層對應于 OSI 七層參考模型的網(wǎng)絡(luò)層。本層包含 IP 協(xié)議、RIP 協(xié)議(路由信息協(xié)議),負責數(shù)據(jù)的包裝、尋址和路由。同時還包含 ICMP (網(wǎng)間控制報文協(xié)議)用來提供網(wǎng)絡(luò)診斷信息。
-
傳輸層:傳輸層對應于 OSI 七層參考模型的傳輸層,它提供兩種端到端的通信服務。其中 TCP協(xié)議提供可靠的數(shù)據(jù)流運輸服務, UDP 協(xié)議提供不可靠的用戶數(shù)據(jù)報服務。
-
應用層:應用層對應于 OSI 七層參考模型的應用層和表示層。因特網(wǎng)的應用層協(xié)議包括 ?FTP (文件傳輸協(xié)議)HTTP (超文本傳輸協(xié)議)、 Telent (遠程終端協(xié)議)、SMTP (簡單郵件傳送協(xié)議)、 IRC (因特網(wǎng)中繼會話)、NNTP (網(wǎng)絡(luò)新聞傳輸協(xié)議)等。
綜上所述,我們需要知道 TCP 協(xié)議在網(wǎng)絡(luò) OSI 的七層模型中的第四層傳輸層, IP 協(xié)議在第三層網(wǎng)絡(luò)層, ARP 協(xié)議在第二層數(shù)據(jù)鏈路層;在第二層上的數(shù)據(jù)叫 Frame ,在第三層上的數(shù)據(jù)叫 Packet ,第四層的數(shù)據(jù)叫 Segment 所有程序的數(shù)據(jù)首先會打包到 TCP 的 Segment 中。
然后 TCP 的 Segment 會打包到 IP 的 Packet ,然后再打包到以太網(wǎng) Ethernet 的 Frame 中,傳到對端后,各個 解析自己的協(xié)議,然后把數(shù)據(jù)交給更高層的協(xié)議處理。
TCP頭格式
在學習 TCP 連接之前,還要學習一下 TCP 頭部格式。因為 TCP 連接建立,需要用 TCP 包來交換和管理數(shù)據(jù),下面看一下 TCP 頭部格式。
TCP 頭部里每個字段都為管理 TCP 連接和控制數(shù)據(jù)流起了重要作用。
16 位端口號:告知主機該報文段是來自哪里(源端口)以及傳給哪個上層協(xié)議或應用程序(目的端口)的。
進行 TCP 通信時,客戶端通常使用系統(tǒng)自動選擇的臨時端口號,而服務器則使用知名服務端口號。所有知名服務使用的端口號都定義在 ?/etc/services 文件中。
32 位序號(sequence number):一次 TCP 通信(從 TCP 連接建立到斷開)過程中個傳輸方向上的字節(jié)流的每個字節(jié)的編號。
32 位確認號(acknowledgement number):用作對另一方發(fā)送來的 TCP 報文段的響應其值是收到的 TCP 報文段的序號值加 1。
4 位頭部長度(header length):標識該 TCP 頭部有多少個 32bit ( 4 Byte 因為最大能表示 15 ,所以 TCP 頭部最長是 60 Byte。
6 位標志位包含如下幾項:
-
URG?標志,表示緊急指針是否有效。
-
ACK?標志,表示確認號是否有效,一般稱攜帶 ACK 標志的 TCP 報文段為"確認報文段"。
-
PSH?標志,提示接收端應用程序應該立即從 TCP 接收緩沖區(qū)中讀走數(shù)據(jù),為接收后續(xù)數(shù)據(jù)騰出空間(如果應用程序不將接收到的數(shù)據(jù)讀走,它們就會直停留在 TCP 接收緩沖區(qū)中)。
-
RST?標志,表示要求對方重新建立連接,一般稱攜帶 RST 標志的 TCP 報文段為"復位報文段"。
-
SYN?標志,表示請求建立 個連接,一般稱攜帶 SYN 標志的 TCP 報文段為"同步報文段"。FIN 標志,表示通知對方本端要關(guān)閉連接了,一般稱攜帶 FIN 標志的 TCP 報文段為"結(jié)束報文段"。
16 位窗口大小(window size):是 TCP 流量控制的一個手段。這里說的窗口,指的是接收通告窗口( Receiver Window, RWND)。它告訴對方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù),這樣對方就可以控制發(fā)送數(shù)據(jù)的速度。
16 位校驗和(TCP checksum):由發(fā)送端填充,接收端對 TCP 報文段執(zhí)行 CRC 算法,以檢驗 TCP 報文段在傳輸過程中是否損壞 。注意,這個校驗不僅包括 TCP 頭部,也包括數(shù)據(jù)部分。這也是 TCP 可靠傳輸?shù)囊粋€重要保障。
16 位緊急指針(urgent pointer):是一個正的偏移量。它和序號字段的值相加表示最后一個緊急數(shù)據(jù)的下一字節(jié)的序號 。確切地說,這個字段是緊急指針相對當前序號的偏移,不妨稱之為“緊急偏移”。TCP 的緊急指針是發(fā)送端向接收端發(fā)送緊急數(shù)據(jù)的方法。
綜上,你需要注意如下幾點:
TCP 的包是沒有 IP 地址的,那是 IP 層上的事,但是有源端口和目的端口。
一個TCP 連接需要四元組( src_ip,src_port,dst_ip,dst_port )來表示是同一個連接 準確說是五元組,還有一個是協(xié)議 但因為這里只是強調(diào) TCP 協(xié)議,所以,只說四元組。
Sequence Number?是包的序號,用來解決網(wǎng)絡(luò)包亂序(reordering )問題。
Acknowledgement Number?就是 ACK ,用于確認收到,用來解決不丟包的問題。
Window Advertised Window?,也就是著名 的滑動窗口 Sliding Window ),用于解決流量控制問題。
TCP Flag?,也就是包的類型,主要是用于操控 TCP 的狀態(tài)機的。
TCP三次握手
其實,網(wǎng)絡(luò)上的傳輸是沒有連接的, TCP 是一樣的 TCP 所謂的 “連接”,其實只不過是在通信的雙方維護一個“連接狀態(tài)”,讓它看上去好像有連接一樣 所以, TCP 的狀態(tài)變換是非常重要的 。
先來看一下著名的三次握手圖。
TCP 連接的建立可以簡單地稱為三次握手,而連接的中止則可以稱為四次揮手。
建立連接 TCP/IP 協(xié)議中, TCP 協(xié)議提供可靠的連接服務,采用三次握手建立一個連接。
-
第一次握手:建立連接時,客戶端發(fā)送 SYN 包到服務器,并進入 SYN_SEND 狀態(tài),等待服務器確認。
-
第二次握手:服務器收到 SYN 包,必須確認客戶的 SYN ,同時自己也發(fā)送一個 SYN 包,即 SYN+ACK 包,此時服務器進入 SYN_RECV 狀態(tài)。
-
第三次握手?:客戶端收到服務器的 SYN + ACK 包,向服務器發(fā)送確認包 ACK,此包發(fā)送完畢,客戶端和服務器進入 ESTABLISHE 態(tài)。
完成 三次握手,客戶端與服務器開始傳送數(shù)據(jù),也就是 ESTABLISHED 狀態(tài)。
連接建立中的異常
建連接時SYN超時問題
如果 server 端因為某種情況沒有收到 client 回來的 ACK,那么,這個連接處還處于一個未建立的狀態(tài)。于是,server端如果在一定時間內(nèi)沒有收到,則 server 端的 TCP 會重發(fā) SYN_ACK。
在Linux下,默認重試次數(shù)為5次,重試的間隔時間從1s開始每次都翻倍,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發(fā)出后還要等32s都知道第5次也超時了。如果第五次重傳之后,還未收到客戶端的 ACK,server 端的 TCP 才會把斷開這個連接。
關(guān)于SYN Flood攻擊
攻擊者短時間偽造不同 IP 地址的 SYN 報文,服務端每接收到一個 SYN 報文,就進入SYN_RCVD 狀態(tài),但服務端發(fā)送出去的 ACK + SYN 報文,無法得到未知 IP 主機的 ACK 應答,久而久之就會占滿服務端的 SYN 接收隊列(未連接隊列),使得服務器不能為正常用戶服務。
避免方式
設(shè)置?tcp_syncookies = 1。當 SYN 隊列滿了后,TCP 會通過源地址端口、目標地址端口和時間戳打造出一個特別的 Sequence Number 發(fā)回去(又叫cookie)。
如果是攻擊者則不會有響應,如果是正常連接,則會把這個 SYN Cookie 發(fā)回來,然后服務端可以通過 cookie 建連接。
設(shè)置?netdev_max_backlog?的值,確定鏈接隊列的大小。當網(wǎng)卡接收數(shù)據(jù)包的速度大于內(nèi)核處理的速度時,會有一個隊列保存這些數(shù)據(jù)包。
通過設(shè)置?netdev_max_backlog?的值,確定 SYN_RCVD 狀態(tài)連接的最大個數(shù)。
通過設(shè)置?tcp_abort_on_overflow?的值。當超出處理能時,對新的 SYN 直接回報 RST,丟棄連接。
TCP四次揮手
TCP的連接斷開
TCP 一個特別的概念叫作半關(guān)閉,這個概念是說, TCP 的連接是全雙工(可以同時發(fā)送和接收)連接,因此在關(guān)閉連接的時候,必須關(guān)閉傳和送兩個方向上的連接。
客戶機給服務器 FIN 的 TCP 報文,然后服務器返回給客戶端一個確認 ACK 報文,并且發(fā)送一個FIN 報文,當客戶機回復 ACK 報文后( 四次握手),連接就結(jié)束了。
在建立連接的時候,通信的雙方要互相確認對方的最大報文長度( MSS ),以便通信。
一般這個 SYN 長度是 MTU 減去固定 IP 首部和 TCP 首部長度。對于一個以太網(wǎng),一般可以達 1460 Byte 。當然如果對于非本地的 IP ,這個 MSS 可能就只有 536 Byte ,而且,如果中間的傳輸網(wǎng)絡(luò)的 MSS 更加的小的話,這個值還會變得更小。
為什么建連接要三次握手,斷連接需要四次揮手?
對于建連接的三次握手,主要是要初始化 Sequence Number 的初始值。通信的雙方要互相通知對方自己的初始化的 Sequence Numbe,所以叫 SYN 。
這個號要作為以后的數(shù)據(jù)通信的序號,以保證應用層接收到的數(shù)據(jù)不會因為網(wǎng)絡(luò)上的傳輸問題而亂序( TCP 會用這個序號來拼接數(shù)據(jù))。
對于四次揮手,其實仔細看則是兩次,因為 TCP 是全雙工的,所以,發(fā)送方和接收方都需要 FIN 和 ACK。
只不過,有一方是被動的,所以看上去就成了所謂的四次揮手 。如果兩邊同時斷連接,那就會就進入到 CLOSING 狀態(tài),接著就是TIME_WAIT 狀態(tài)。
斷開連接中的異常
TIME_WAIT數(shù)量太多
從上面的描述可以知道,TIME_WAIT 是個很重要的狀態(tài),但是如果在大并發(fā)的短鏈接下,TIME_WAIT 就會太多。TIME_WAIT過多會占用大量的內(nèi)存資源和端口資源。
優(yōu)化法一:tcp_tw_reuse
設(shè)置tcp_tw_reuse = 1,則可以復用處于 TIME_WAIT 的 socket 為新的連接所用。
有一點需要注意的是,tcp_tw_reuse 功能只能用客戶端(連接發(fā)起方),因為開啟了該功能,在調(diào)用 connect() 函數(shù)時,內(nèi)核會隨機找一個 time_wait 狀態(tài)超過 1 秒的連接給新的連接復用。
使用 tcp_timestamps = 1 選項,還有一個前提,需要打開對 TCP 時間戳的支持,即這個時間戳的字段是在 TCP 頭部的「選項」里,用于記錄 TCP 發(fā)送方的當前時間戳和從對端接收到的最新時間戳。
由于引入了時間戳,我們在前面提到的 2MSL 問題就不復存在了,因為重復的數(shù)據(jù)包會因為時間戳過期被自然丟棄。
優(yōu)化法二:tcp_max_tw_buckets
這個值默認為 18000,當系統(tǒng)中處于 TIME_WAIT 的連接一旦超過這個值時,系統(tǒng)就會將后面的 TIME_WAIT 連接狀態(tài)重置。
這個方法過于暴力,而且治標不治本,帶來的問題遠比解決的問題多,不推薦使用。
TCP狀態(tài)流轉(zhuǎn)
接下來再看一下著名的 TCP 狀態(tài)流轉(zhuǎn)圖。
CLOSED狀態(tài):表示初始狀態(tài)。
LISTEN狀態(tài):表示服務器端的某個 socket 處于監(jiān)聽狀態(tài),可以接受連接。
SYN_SENT狀態(tài):在服務端監(jiān)聽后,客戶端 socket 執(zhí)行 CONNECT 連接時,客戶端發(fā)送 SYN 報文,此時客戶端就進入 SYN_SENT 狀態(tài),等待服務端的確認。
SYN_RCVD狀態(tài):表示服務端接收到了SYN 報文,在正常情況下,這個狀態(tài)是服務器端的 socket 在建立 TCP 連接時的三次握手會話過程中的一個中間狀態(tài),很短暫,基本上用網(wǎng)絡(luò)查詢工具 netstat 是很難看到這種狀態(tài)的。因此這種狀態(tài)時,當收到客戶端的 ACK 報文后,它會進入到 ESTABLISHED 狀態(tài)。
ESTABLISHED狀態(tài):表示連接已經(jīng)建立了。
FIN_WAIT_1狀態(tài):這個是已經(jīng)建立連接之后,其中一方請求終止連接,等待對方的 FIN 報文 。
FIN_WAIT_1 狀態(tài)是當 socket 在 ESTABLISHED 狀態(tài)時,它想主動關(guān)閉連接,向?qū)Ψ桨l(fā)送了 FIN 報文,此時該 socket 即進入到 FIN_WAIT_1 狀態(tài)。而當對方回應 ACK 報文后,則進入到 FIN_WAIT_2 狀態(tài)。
當然在實際的正常情況下,無論對方處于何種情況,都應該馬上回應 ACK 報文,所以 FIN_WAIT_1 狀態(tài)一般是比較難見到的,而 FIN_WAIT_2 狀態(tài)還可以用 netstat 看到。
FIN_WAIT_2狀態(tài):實際上 FIN_WAIT_2 狀態(tài)下的 socket ,表示半連接,即有一方要求關(guān)閉連接,但另外還告訴對方:我暫時還有點數(shù)據(jù)需要傳送給你,請稍后再關(guān)閉連接。
TIME_ WAIT狀態(tài):表示收到了對方的 FIN 報文,并發(fā)送出了 ACK 報文,就等 2MSL 后即可回到 CLOSED 可用狀態(tài)了。如果在 FIN_WAIT_1 狀態(tài)下,收到了對方同時帶 FIN 標志和 ACK 標志的報文時,可以直接進入到 TIME_WAIT 狀態(tài),而無需經(jīng)過 FIN_WAIT_2 狀態(tài)。
CLOSING狀態(tài):這種狀態(tài)比較特殊,實際情況中應該是很少見。正常情況下,當發(fā)送 FIN 報文后,按理來說是應該先收到(或同時收到)對方的ACK 報文,再收到對方的 FIN 報文 。但是 CLOSING 狀態(tài)表示你發(fā)送 FIN 報文后,并沒有收到對方的 ACK 報文,反而收到了對方的 FIN 報文 。
如果雙方幾乎在同時關(guān)閉一個 socket 的話,那么就出現(xiàn)了雙方同時發(fā)送 FIN 報文的情況,就會出現(xiàn) CLOSING 狀態(tài),表示雙方都正在關(guān)閉 socket 連接。
CLOSE_WAIT狀態(tài):表示在等待關(guān)閉。當對方關(guān)閉一個 socket 后發(fā)送 FIN 報文給自己時,系統(tǒng)將毫無疑問地會回應 ACK 報文給對方,此時則進入到 CLOSE_WAIT 狀態(tài)。
接下來呢,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有,那么你也就可以關(guān)閉這個socket了,發(fā)送 FIN 報文給對方,即關(guān)閉連接 。CLOSE _WAIT 狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接。
LAST_ACK狀態(tài):這個狀態(tài)還是比較好理解的,它是被動關(guān)閉 方在發(fā)送 FIN 報文后,最后等待對方的 ACK 報文。
CLOSED狀態(tài):當收到 ACK 報文后,也即可以進入到 CLOSED 可用狀態(tài)了。
2MSL 等待狀態(tài):在 FIN_WAIT_2 發(fā)送了最后一個 ACK 數(shù)據(jù)報以后,要進入 TIME_WAIT 態(tài),這個狀態(tài)是防止最后一次握手的數(shù)據(jù)報沒有傳送到對方那里而準備的。
由于 socket 2MSL 狀態(tài),使得應用程序在 2MSL 時間內(nèi)無法再次使用同一個 socket ,對于客戶程序還好 些,但是對于服務程序(httpd),它總是要使用同一個端口來進行服務,而在 2MSL 時間內(nèi),啟動 httpd 就會出現(xiàn)錯誤(插口被使用)。
為了避免這個錯誤,服務器給出了一個平靜時間的概念,這是說在 2MSL的時間內(nèi),雖然可以重新啟動服務器,但是這個服務器還是要平靜地等待 2MSL 的時間才能進行下一次連接。
FIN WAIT_2 狀態(tài):這就是著名的半關(guān)閉狀態(tài)了,這是在關(guān)閉連接時,客戶端和服務器兩次握手之后的狀態(tài) 。
在這個狀態(tài)下,應用程序還有接收數(shù)據(jù)的能力。已經(jīng)無法發(fā)送數(shù)據(jù),但是也有一種可能是,客戶端處于FIN_WAIT_2 狀態(tài),而服務器則一直處于 WAIT_CLOSE 狀態(tài),直到應用層來決定關(guān)閉這個狀態(tài)。
RST 同時打開和同時關(guān)閉:RST 是另一種關(guān)閉連接的方式,應用程序應該可以判斷RST 包的真實性,即是否為異常中止 而同時打開和同時關(guān)閉則是兩種特殊的 TCP 狀態(tài),發(fā)生的概率很小。
總結(jié)
本文主要講述了網(wǎng)絡(luò)分層模型,以及各層的作用,數(shù)據(jù)包是怎么組裝和拆包的。TCP 包結(jié)構(gòu)也大致學習了下,還有 TCP 連接的建立和斷開。
TCP 連接建立之后才開始發(fā)數(shù)據(jù)包,所以 TCP 三次握手很重要。TCP 三次握手中也可能存在一些異常,只有徹底搞懂三次握手才能正確處理這些異常。
TCP 四次揮手也很重要,server 中經(jīng)常要接受和斷開連接。對應斷開連接中的異常,以及服務器請求量過多,只有在搞懂 TCP 四次揮手以后,處理這些問題才能得心應手
總結(jié)
以上是生活随笔為你收集整理的TCP 连接的前世今生的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 经典Golang语法50问!
- 下一篇: PHP的数组结构是用哈希表实现的