理解TCP/IP協議
一、協議
在計算機網路與資訊通訊領域裡,人們經常提及 “協議” 一詞。網際網路中常用的協議有HTTP、TCP、IP等。
協議的必要性
簡單來說,協議就是計算機與計算機之間通過網路通訊時,事先達成的一種 “約定”。這種“約定”使不同廠商的裝置、不同的CPU以及不同作業系統組成的計算機之間,只要遵循相同的協議就能夠實現通訊。這就好比一箇中國人說漢語一個外國人說英語使用不同的國家語言進行溝通,怎麼也無法理解。如果兩個人約定好 都說中文或英文,就可以互相溝通通訊。協議分為很多種,每一種協議都明確界定了它的行為規範。兩臺計算機必須能夠支援相同的協議,並遵循相同協議進行處理,這樣才能實現相互通訊。
二、協議分層
TCP/IP協議
TCP/IP 是用於因特網 (Internet) 的通訊協議。 TCP/IP 通訊協議是對計算機必須遵守的規則的描述,只有遵守這些規則,計算機之間才能進行通訊。
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)協議屬於傳輸層協議。其中TCP提供IP環境下的資料可靠傳輸,它提供的服務包括資料流傳送、可靠性、有效流控、全雙工操作和多路復 用。通過面向連線、端到端和可靠的資料包傳送。通俗說,它是事先為所傳送的資料開闢出連線好的通道,然後再進行資料傳送;而UDP則不為IP提供可靠性、 流控或差錯恢復功能。一般來說,TCP對應的是可靠性要求高的應用,而UDP對應的則是可靠性要求低、傳輸經濟的應用。 TCP支援的應用協議主要有:Telnet、FTP、SMTP等; UDP支援的應用層協議主要有:NFS(網路檔案系統)、SNMP(簡單網路管理協議)、DNS(主域名稱系統)、TFTP(通用檔案傳輸協議)等。 TCP/IP協議與低層的資料鏈路層和物理層無關,這也是TCP/IP的重要特點
- TCP(Transimision Control Protocal)
- 傳輸控制協議
- 可靠的、面向連線的協議
- 傳輸效率低
- UDP(User Datagram Protocal)
- 使用者資料包協議
- 不可靠的、無連線的服務
- 傳輸效率高
TCP/IP協議族
TCP/IP是基於TCP和IP這兩個最初的協議之上的不同的通訊協議的大集合
協議的分層
網路協議通常分不同層次進行開發,每一層分別負責不同的通訊功能。一個協議族,比如TCP/IP,是一組不同層次上的多個協議的組合。 傳統上來說 TCP/IP 被認為是一個四層協議, 而ISO(國際標準化組織),制定了一個國際標準OSI七層協議模型,OSI協議以OSI參考模型為基礎界定了每個階層的協議和每個階層之間介面相關的標準。
分層的作用
應用層
應用層為作業系統或網路應用程式提供訪問網路服務的介面。應用層協議的代表包括:Telnet、FTP、HTTP、SNMP等。
表示層
將應用處理的資訊轉換為適合網路傳輸的格式,或將來自下一層的資料轉換為上層能夠處理的格式。資料的表示、安全、壓縮。
會話層
負責建立和斷開通訊連線(資料流動的邏輯通路),以及資料的分割等資料傳輸相關的管理。
傳輸層
管理兩個節點之間的資料傳輸。負責可靠傳輸(確保資料被可靠地傳送到目標地址)。
網路層
地址管理與路由選擇, 在這一層,資料的單位稱為資料包(packet)(路由器)。
資料鏈路層
互連裝置之間傳送和識別資料幀(交換機)。
物理層
以"0"、 "1"代表電壓的高低,燈光的閃滅,在這一層,資料的單位稱為位元(bit),(中繼器、集線器、還有我們通常說的雙絞線也工作在物理層)。
七層通訊
傳送方由第七層到第一層 由上到下按照順序傳送資料,每個分層在處理上層傳遞的資料時,附上當前層協議所必須的 "首部"資訊。接收方由第一層到第七層 由下到上按照順序傳遞資料,每個分層對接收到的資料進行 "首部"與"內容"分離,在轉發給上一層。最終將傳送的資料恢復為原始資料。
三、傳輸方式的分類
網路通訊科根據資料傳送方法進行多種分類,分類方法很多,下面列舉幾種常見的:
- 面向有連線型和麵向無連線型 1.1 面向有連線型
傳送資料之前,需要在收發主機之間建立一條通訊線路,在通訊傳輸前後,專門進行建立和斷開連線的處理,如果與對端之間無法通訊,可避免傳送無謂的資料
1.2面向無連線型
四、報文、幀、資料包等的區別
報文(message)是網路中交換與傳輸的資料單元,也是網路傳輸的單元。報文包含了將要傳送的完整的資料資訊,其長短不需一致。報文在傳輸過程中會不斷地封裝成分組、包、幀來傳輸,封裝的方式就是新增一些控制資訊組成的首部,那些就是報文頭。
應用層:報文(message),一般指完整的資訊,傳輸層實現報文交付,位於應用層的資訊分組稱為報文; 傳輸層:報文段(segment),組成報文的每個分組; 網路層:分組(packet)是網路傳輸中的二進位制格式單元,資料包(datapacket)是TCP/IP通訊協議傳輸中的資料單位;通過網路傳輸的資料基本單元,包含一個報頭和資料本身,其中報頭描述了資料的目的地及其與其他資料之間的關係,可以理解為資料傳輸的分組,我們將通過網路傳輸的基本資料單元稱為資料包(Datagram); 鏈路層:幀(frame),資料鏈路層的協議資料單元,為了保證資料的可靠傳輸,把使用者資料封裝成幀; 物理層:PDU(bit),協議資料單元; 抓包,抓到的是傳輸層的包,packet/frame/Datagram/segment是存在於同條記錄中的,這些是基於所在協議層的不同取了不同的名字。
五、TCP報文
資料包
IP 資料包在乙太網資料包的負載裡面,TCP資料包在IP資料包的負載裡。
TCP 首部各欄位的意義和作用
TCP首部最小為20位元組,這20位元組分為5行,每行4個位元組也就是32個位。
源埠和目的埠 Port
-
源埠號:16位的源埠中包含初始化通訊的埠。源埠和源IP地址的作用是標識報文的返回地址。
-
目的埠號:16位的目的埠域定義傳輸的目的。這個埠指明報文接收計算機上的應用程式地址介面。
計算機通過埠號識別訪問哪個服務,比如http服務或ftp服務,傳送方埠號是進行隨機埠,目標埠號決定了接收方哪個程式來接收 分別佔用16位,也就是埠號最大是2^16,所以埠號的範圍是0~65536
埠號的分配:
- 知名埠號一般位於:1 --- 255 之間
- 256 --- 1023的埠號,通常是由Unix系統佔用(系統佔用)
- 1024 ---5000 是大多數TCP、IP實現的臨時分配
- 大於5000的一般是給其他服務預留的(Internet上並不常用的服務)
序號 Sequence Number
TCP用序列號對資料包進行標記,以便在到達目的地後重新重灌,假設當前的序列號為 s,傳送資料長度為 l,則下次傳送資料時的序列號為 s + l。在建立連線時通常由計算機生成一個隨機數作為序列號的初始值。
確認號 Acknowledgemt Number
佔 4 個位元組,表示期望收到對方下一個報文段的序號值。 TCP 的可靠性,是建立在「每一個資料包文都需要確認收到」的基礎之上的。
就是說,通訊的任何一方在收到對方的一個報文之後,都要傳送一個相對應的「確認報文」,來表達確認收到。 那麼,確認報文,就會包含確認號。 例如,通訊的一方收到了第一個 25kb 的報文,該報文的 序號值=0,那麼就需要回復一個確認報文,其中的確認號 = 25600.
資料偏移 Offset
佔 0.5 個位元組 (4 位)。 這個欄位實際上是指出了 TCP 報文段的首部長度 ,它指出了 TCP報文段的資料起始處 距離 TCP報文的起始處 有多遠。(注意 資料起始處 和 報文起始處 的意思)
一個資料偏移量 = 4 byte,由於 4 位二進位制數能表示的最大十進位制數字是 15,因此資料偏移的最大值是 60 byte,這也側面限制了 TCP 首部的最大長度。
保留 Reserved
佔 0.75 個位元組 (6 位)。 保留為今後使用,但目前應置為 0。
標誌位 TCP Flags
標誌位,一共有 6 個,分別佔 1 位,共 6 位 。 每一位的值只有 0 和 1,分別表達不同意思。
- ACK:確認序號有效
- RST:重置連線
- SYN:發起了一個新連線
- FIN:釋放一個連線
確認 ACK (Acknowlegemt)
當 ACK = 1 的時候,確認號(Acknowledgemt Number)有效。 一般稱攜帶 ACK 標誌的 TCP 報文段為「確認報文段」。為0表示資料段不包含確認資訊,確認號被忽略。
TCP 規定,在連線建立後所有傳送的報文段都必須把 ACK 設定為 1。
推送 PSH (Push)
當 PSH = 1 的時候,表示該報文段高優先順序,接收方 TCP 應該儘快推送給接收應用程式,而不用等到整個 TCP 快取都填滿了後再交付。
復位 RST (Reset)
當 RST = 1 的時候,表示 TCP 連線中出現嚴重錯誤,需要釋放並重新建立連線。 一般稱攜帶 RST 標誌的 TCP 報文段為「復位報文段」。
同步 SYN (SYNchronization)
當 SYN = 1 的時候,表明這是一個請求連線報文段。 一般稱攜帶 SYN 標誌的 TCP 報文段為「同步報文段」。 在 TCP 三次握手中的第一個報文就是同步報文段,在連線建立時用來同步序號。
對方若同意建立連線,則應在響應的報文段中使 SYN = 1 和 ACK = 1。
終止 FIN (Finis)
當 FIN = 1 時,表示此報文段的傳送方的資料已經傳送完畢,並要求釋放 TCP 連線。
一般稱攜帶 FIN 的報文段為「結束報文段」。
在 TCP 四次揮手釋放連線的時候,就會用到該標誌。
視窗大小 Window Size
佔 2 位元組。
該欄位明確指出了現在允許對方傳送的資料量,它告訴對方本端的 TCP 接收緩衝區還能容納多少位元組的資料,這樣對方就可以控制傳送資料的速度。 視窗大小的值是指,從本報文段首部中的確認號算起,接收方目前允許對方傳送的資料量。
例如,假如確認號是 701 ,視窗欄位是 1000。這就表明,從 701 號算起,傳送此報文段的一方還有接收 1000 (位元組序號是 701 ~ 1700) 個位元組的資料的接收快取空間。
校驗和 TCP Checksum
佔 2 個位元組。 由傳送端填充,接收端對 TCP 報文段執行 CRC 演算法,以檢驗 TCP 報文段在傳輸過程中是否損壞,如果損壞這丟棄。
檢驗範圍包括首部和資料兩部分,這也是 TCP 可靠傳輸的一個重要保障。
緊急指標 Urgent Pointer
佔 2 個位元組。 僅在 URG = 1 時才有意義,它指出本報文段中的緊急資料的位元組數。 當 URG = 1 時,傳送方 TCP 就把緊急資料插入到本報文段資料的最前面,而在緊急資料後面的資料仍是普通資料。
因此,緊急指標指出了緊急資料的末尾在報文段中的位置。
六、三次握手,四次揮手
需要了解的資訊:
-
ACK : TCP協議規定,只有ACK=1時有效,也規定連線建立後所有傳送的報文的ACK必須為1
-
SYN(SYNchronization) : 在連線建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連線請求報文。對方若同意建立連線,則應在響應報文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個連線請求或連線接受報文。
-
FIN (finis)即完,終結的意思, 用來釋放一個連線。當 FIN = 1 時,表明此報文段的傳送方的資料已經傳送完畢,並要求釋放連線。
三次握手 建立連線
TCP(Transmission Control Protocol,傳輸控制協議)是 面向連線的協議,也就是說在收發資料之前,必須先和對方建立連線
一個TCP連線必須要經過三次“對話”才能建立起來,其中的過程非常複雜,只簡單的 描述下這三次對話的簡單過程:主機A向主機B發出連線請求資料包:“我想給你發資料,可以嗎?”,這是第一次對話;主機B向主機A傳送同意連線和要求同步 (同步就是兩臺主機一個在傳送,一個在接收,協調工作)的資料包:“可以,你什麼時候發?”,這是第二次對話;主機A再發出一個資料包確認主機B的要求同 步:“我現在就發,你接著吧!”,這是第三次對話。三次“對話”的目的是使資料包的傳送和接收同步,經過三次“對話”之後,主機A才向主機B正式傳送數 據。
首先由Client發出請求連線即 SYN=1 ACK=0 (請看頭欄位的介紹), TCP規定SYN=1時不能攜帶資料,但要消耗一個序號,因此宣告自己的32位序號是 seq=x,然後 Server 進行回覆確認,即 SYN=1 ACK=1 seq=y, ack=x+1, 再然後 Client 再進行一次確認,但不用SYN 了,這時即為 ACK=1, seq=x+1, ack=y+1.
四次揮手 釋放連線
當客戶A 沒有東西要傳送時就要釋放 A 這邊的連線,A會傳送一個報文(沒有資料),其中 FIN 設定為1, 伺服器B收到後會給應用程式一個信,這時A那邊的連線已經關閉,即A不再傳送資訊(但仍可接收資訊)。 A收到B的確認後進入等待狀態,等待B請求釋放連線, B資料傳送完成後就向A請求連線釋放,也是用FIN=1 表示, 並且用 ack = u+1(如圖), A收到後回覆一個確認資訊,並進入 TIME_WAIT 狀態, 等待 2MSL 時間。
關於 TIME_WAIT 過渡到 CLOSED 狀態說明: 從 TIME_WAIT 進入 CLOSED 需要經過 2MSL,其中 MSL 就叫做 最長報文段壽命(Maxinum Segment Lifetime),根據 RFC 793 建議該值這是為 2 分鐘,也就是說需要經過 4 分鐘,才進入 CLOSED 狀態。
為什麼要等待呢?
為了這種情況: B向A傳送 FIN = 1 的釋放連線請求,但這個報文丟失了, A沒有接到不會傳送確認資訊, B 超時會重傳,這時A在 WAIT_TIME 還能夠接收到這個請求,這時再回復一個確認就行了。(A收到 FIN = 1 的請求後 WAIT_TIME會重新記時)
另外伺服器B存在一個保活狀態,即如果A突然故障當機了,那B那邊的連線資源什麼時候能釋放呢? 就是保活時間到了後,B會傳送探測資訊, 以決定是否釋放連線
為什麼連線的時候是三次握手,關閉的時候卻是四次握手?
答:因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都傳送完了,我才能傳送FIN報文,因此不能一起傳送。故需要四步握手。