TCP/IP(四):TCP 與 UDP 協議簡介

從本章開始,我們開始介紹最重要的傳輸層。傳輸層位于 OSI 七層模型的第四層(由下往上)。顧名思義,傳輸層的主要作用是實現應用程序之間的通信。網絡層主要是保證不同數據鏈路下數據的可達性,至于如何傳輸數據則是由傳輸層負責。

傳輸層協議簡介

常見的傳輸層協議主要有 TCP 協議和 UDP 協議。TCP 協議是面向有連接的協議,也就是說在使用 TCP 協議傳輸數據之前一定要在發送方和接收方之間建立連接。一般情況下建立連接需要三步,關閉連接需要四步。

建立 TCP 連接后,由于有數據重傳、流量控制等功能,TCP 協議能夠正確處理丟包問題,保證接收方能夠收到數據,與此同時還能夠有效利用網絡帶寬。然而 TCP 協議中定義了很多復雜的規范,因此效率不如 UDP 協議,不適合實時的視頻和音頻傳輸。

UDP 協議是面向無連接的協議,它只會把數據傳遞給接收端,但是不會關注接收端是否真的收到了數據。但是這種特性反而適合多播,實時的視頻和音頻傳輸。因為個別數據包的丟失并不會影響視頻和音頻的整體效果。

IP 協議中的兩大關鍵要素是源 IP 地址和目標 IP 地址。而剛剛我們說過,傳輸層的主要作用是實現應用程序之間的通信。因此傳輸層的協議中新增了三個要素:源端口號,目標端口號和協議號。通過這五個信息,可以唯一識別一個通信。

不同的端口用于區分同一臺主機上不同的應用程序。假設你打開了兩個瀏覽器,瀏覽器 A 發出的請求不會被瀏覽器 B 接收,這就是因為 A 和 B 具有不同的端口。

協議號用于區分使用的是 TCP 還是 UDP。因此相同兩臺主機上,相同的兩個進程之間的通信,在分別使用 TCP 協議和 UDP 協議時也可以被正確的區分開來。

用一句話來概括就是:“源 IP 地址,目標 IP 地址,源端口號,目標端口號和協議號”這五個信息只要有一個不同,都被認為是不同的通信。

UDP 首部

UDP 協議最大的特點就是簡單,它的首部如下圖所示:


UPD 首部

包長度表示 UDP 首部的長度和 UPD 數據長度之和。

校驗和用來判斷數據在傳輸過程中是否損壞。計算這個校驗和的時候,不僅考慮源端口號和目標端口號,還要考慮 IP 首部中的源 IP 地址,目標 IP 地址和協議號(這些又稱為 UDP 偽首部)。這是因為以上五個要素用于識別通信時缺一不可,如果校驗和只考慮端口號,那么另外三個要素收到破壞時,應用就無法得知。這有可能導致不該收到包的應用收到了包,改收到包的應用反而沒有收到。

這個概念同樣適用于即將介紹的 TCP 首部。

TCP 首部

和 UDP 首部相比,TCP 首部要復雜得多。解析這個首部的時間也相應的會增加,這是導致 TCP 連接的效率低于 UDP 的原因之一。


TCP 首部

其中某些關鍵字段解釋如下:

  • 序列號:它表示發送數據的位置,假設當前的序列號為 s,發送數據長度為 l,則下次發送數據時的序列號為 s + l。在建立連接時通常由計算機生成一個隨機數作為序列號的初始值。

  • 確認應答號:它等于下一次應該接收到的數據的序列號。假設發送端的序列號為 s,發送數據的長度為 l,那么接收端返回的確認應答號也是 s + l。發送端接收到這個確認應答后,可以認為這個位置以前所有的數據都已被正常接收。

  • 數據偏移:TCP 首部的長度,單位為 4 字節。如果沒有可選字段,那么這里的值就是 5。表示 TCP 首部的長度為 20 字節。

  • 控制位:改字段長度為 8 比特,分別有 8 個控制標志。依次是 CWR,ECE,URG,ACK,PSH,RST,SYN 和 FIN。在后續的文章中你會陸續接觸到其中的某些控制位。

  • 窗口大小:用于表示從應答號開始能夠接受多少個 8 位字節。如果窗口大小為 0,可以發送窗口探測。

  • 緊急指針:盡在 URG 控制位為 1 時有效。表示緊急數據的末尾在 TCP 數據部分中的位置。通常在暫時中斷通信時使用(比如輸入 Ctrl + C)。

TCP 握手

TCP 是面向有連接的協議,連接在每次通信前被建立,通信結束后被關閉。了解連接建立和關閉的過程通常是考察的重點。連接的建立和關閉過程可以用一張圖來表示:


TCP 連接建立和關閉

通常情況下,我們認為客戶端首先發起連接。

三次握手建立連接

這個過程可以用以下三句形象的對話表示:

  1. (客戶端):我要建立連接了。
  2. (服務端):我知道你要建立連接了,我這邊沒有問題。
  3. (客戶端):我知道你知道我要建立連接了,接下來我們就正式開始通信。

為什么是三次握手

根據一般的思路,我們可能會覺得只要兩次握手就可以了,第三步確認看似是多余的。那么 TCP 協議為什么還要費力不討好的加上這一次握手呢?

這是因為在網絡請求中,我們應該時刻記住:“網絡是不可靠的,數據包是可能丟失的”。假設沒有第三次確認,客戶端向服務端發送了 SYN,請求建立連接。由于延遲,服務端沒有及時收到這個包。于是客戶端重新發送一個 SYN 包。回憶一下介紹 TCP 首部時提到的序列號,這兩個包的序列號顯然是相同的。

假設服務端接收到了第二個 SYN 包,建立了通信,一段時間后通信結束,連接被關閉。這時候最初被發送的 SYN 包剛剛抵達服務端,服務端又會發送一次 ACK 確認。由于兩次握手就建立了連接,此時的服務端就會建立一個新的連接,然而客戶端覺得自己并沒有請求建立連接,所以就不會向服務端發送數據。從而導致服務端建立了一個空的連接,白白浪費資源。

在三次握手的情況下,服務端直到收到客戶端的應答后才會建立連接。因此在上述情況下,客戶端會接受到一個相同的 ACK 包,這時候它會拋棄這個數據包,不會和服務端進行第三次握手,因此避免了服務端建立空的連接。

ACK 確認包丟失怎么辦

三次握手其實解決了第二步的數據包丟失問題。那么第三步的 ACK 確認丟失后,TCP 協議是如何處理的呢?

按照 TCP 協議處理丟包的一般方法,服務端會重新向客戶端發送數據包,直至收到 ACK 確認為止。但實際上這種做法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊,是指發送方偽造多個 IP 地址,模擬三次握手的過程。當服務器返回 ACK 后,攻擊方故意不確認,從而使得服務器不斷重發 ACK。由于服務器長時間處于半連接狀態,最后消耗過多的 CPU 和內存資源導致死機。

正確處理方法是服務端發送 RST 報文,進入 CLOSE 狀態。這個 RST 數據包的 TCP 首部中,控制位中的 RST 位被設置為 1。這表示連接信息全部被初始化,原有的 TCP 通信不能繼續進行。客戶端如果還想重新建立 TCP 連接,就必須重新開始第一次握手。

四次握手關閉連接

這個過程可以用以下四句形象的對話表示:

  1. (客戶端):我要關閉連接了。
  2. (服務端):你那邊的連接可以關閉了。
  3. (服務端):我這邊也要關閉連接了。
  4. (客戶端):你那邊的連接可以關閉了。

由于連接是雙向的,所以雙方都要主動關閉自己這一側的連接。

關閉連接的最后一個 ACK 丟失怎么辦

實際上,在第三步中,客戶端收到 FIN 包時,它會設置一個計時器,等待相當長的一段時間。如果客戶端返回的 ACK 丟失,那么服務端還會重發 FIN 并重置計時器。假設在計時器失效前服務器重發的 FIN 包沒有到達客戶端,客戶端就會進入 CLOSE 狀態,從而導致服務端永遠無法收到 ACK 確認,也就無法關閉連接。

示意圖如下:


TCP 關閉連接


文/bestswifter(簡書作者)
原文鏈接:http://www.jianshu.com/p/dc456cf57e06
著作權歸作者所有,轉載請聯系作者獲得授權,并標注“簡書作者”。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248008.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248008.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248008.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Node — 第二天

http模塊 搭建服務器的步驟 ① 導入 http 模塊 ② 創建 web 服務器實例 ③ 為服務器實例綁定 request 事件,監聽客戶端的請求 ④ 啟動服務器 // ① 導入 http 模塊 const http require(http);// ② 創建 web 服務器實例 const server http.createServer();/…

《學習之道》第九章不要突擊工作

靈感從天而降的時刻確實是存在的。 這樣少見的創造性突破,通常是在經歷了一番神經緊張的準備、竭盡全力的努力,甚至包括熬夜工作后才姍姍來遲。這與 數學 和 科學標準的一天學習 是大不相同的。 它更像體育運動:每隔一陣子會有一天的比賽&…

TCP/IP(五):TCP 協議詳解

上一節 中講過,TCP 協議是面向有連接的協議,它具有丟包重發和流量控制的功能,這是它區別于 UDP 協議最大的特點。本文就主要討論這兩個功能。 數據包重發 數據發送 丟包重發的前提是發送方能夠知道接收方是否成功的接收了消息。所以&#…

nodeJS — 學習的筆記

Node介紹 為什么要學習Node.js 企業需求 具有服務端開發經驗更改front-endback-end全棧開發工程師基本的網站開發能力 服務端前端運維部署 多人社區 [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MVqHkEIo-1588084625862)(C:\Users\A\AppData\R…

TCP/IP(六):HTTP 與 HTTPS 簡介

本文是準備面試過程中網絡部分總結整理的最后一篇文章,主要介紹以下知識: HTTP 協議概述POST 請求和 GET 請求Cookie 和 Session數據傳輸時的加密HTTPS 簡介 HTTP 協議 在 OSI 七層模型中,HTTP 協議位于最頂層的應用層中。通過瀏覽器訪問網…

Node — 第三天

模塊化 什么是模塊化 模塊化是指解決一個復雜問題時,自頂向下逐層把系統劃分成若干模塊的過程。 對于整個系統來說,模塊是可組合、分解和更換的單元。 生活中的模塊化 編程中的模塊化 編程領域中的模塊化,就是遵守固定的規則,…

FireDAC 中文字段過濾問題

當使用 FireDAC Filter 過濾數據的時候,通常這樣寫: FDMemTable.Filtered : False; FDMemTable1.Filter : 姓名 string(edtFilter.Text).QuotedString; FDMemTable.Filtered : True; 將會報錯:[FireDAC][Stan][Eval]-107. Invalid characte…

UIScrollViewDelegate-代理API詳解

在iOS編程中,經常用到UIScrollView控件。自然也會用到UIScrollViewDelegate協議。 今天就抽空,研究了一下UIScrollViewDelegate中所有的委托方法。 僅做Mark!如有,錯誤之處,歡迎留言指正,交流!貼…

License for package Android SDK Build-Tools 28.0.2 not accepted.(MAC)

https://blog.csdn.net/user11223344abc/article/details/83997907轉載于:https://www.cnblogs.com/dtdxrk/p/10812469.html

Express — 使用步驟

Express Express 介紹安裝搭建服務器的步驟express提供的新方法GET接口 獲取GET中的請求參數 POST接口 獲取POST請求提交的數據 中間件原理中間件語法中間件初體驗(設置響應頭)中間件開放靜態資源中間件接收POST請求體中間件返回404頁面 express 介紹 E…

大模型工具_Langchain-Chatchat

https://github.com/chatchat-space/Langchain-Chatchat 原Langchain-ChatGLM 1 功能 整體功能,想解決什么問題 基于 Langchain 與 ChatGLM 等LLM模型,搭建一套針對中文場景與開源模型,界面友好、可離線運行的知識庫問答解決方案。 當前解決…

iOS 鍵盤風格詳解UIKeyboardType

一、鍵盤風格 UIKit框架支持8種風格鍵盤。 [java] view plaincopy print?typedef enum { UIKeyboardTypeDefault, // 默認鍵盤:支持所有字符 UIKeyboardTypeASCIICapable, // 支持ASCII的默認鍵盤 UIKeyboardTypeNu…

MySQL Hardware--FIO壓測

FIO參數 filename/export/1.txt 支持文件系統或者裸設備,-filename/dev/sda2或-filename/dev/sdb direct1 測試過程繞過機器自帶的buffer,使測試結果更真實 rwrandwread 測試隨機讀的I/O rwrandwrite 測試隨機…

Node — 第四天(Promise與路由)

Promise - ES6新對象 Promise能夠處理異步程序。 回調地獄 JS中或node中,都大量的使用了回調函數進行異步操作,而異步操作什么時候返回結果是不可控的,如果我們希望幾個異步請求按照順序來執行,那么就需要將這些異步操作嵌套起來…

xcode8 升級后注釋快捷鍵不能使用的解決方法

一種說法: 這個是因為蘋果解決xcode ghost。把插件屏蔽了。解決方法 命令運行: sudo /usr/libexec/xpccachectl 然后必須重啟電腦后生效 還有一種說法:不用指令直接重啟就可以了。

winform datagridview控件使用

最近做項目時&#xff0c;顯示查詢結果總需要綁定到datagridview控件上顯示&#xff0c;總結了給datagridview綁定數據的方式&#xff0c;以及導出datagridview數據到excel表格&#xff0c;如有錯誤請多指教 1.直接綁定數據源&#xff0c;可以綁定的數據格式有List<T>,Da…

Node — 第五天

1. MySQL數據庫 phpstudy 數據庫服務器及圖形化軟件 軟件鏈接 鏈接&#xff1a;https://pan.baidu.com/s/1F8wdoMstHAJkINfDKDejsw 提取碼&#xff1a;xl3k 數據庫對于我們前端同學來說&#xff0c;就是一個了解。 對于不會變化的數據&#xff08;省、市、縣&#xff09;&…

iOS10 權限訪問崩潰

手機升級了 iOS10 Beta&#xff0c;然后用正在開發的項目 裝了個ipa包&#xff0c;發現點擊有關 權限訪問 直接Crash了&#xff0c;并在控制臺輸出了一些信息&#xff1a; This app has crashed because it attempted to access privacy-sensitive data without a usage descr…

Node — 第六天(前后端分離)及(身份驗證)

綜合應用服務端知識點搭建項目 下載安裝所需的第三方模塊 npm init -y npm i express cors mysql # express 用于搭建服務器 # cors 用于解決跨域 # mysql 用于操作數據庫# 后面用到什么&#xff0c;再下載創建app.js 之前&#xff0c;我們開啟一個服務器&#xff0c;js文件…

繼承上機作業

1、實現如下類之間的繼承關系&#xff0c;并編寫Music類來測試這些類 2、編寫一個Java應用程序&#xff0c;該程序包括3個類&#xff1a;Monkey類、People類和主類E。要求&#xff1a; (1) Monkey類中有個構造方法&#xff1a;Monkey (String s)&#xff0c;并且有個public voi…