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

上一節 中講過,TCP 協議是面向有連接的協議,它具有丟包重發和流量控制的功能,這是它區別于 UDP 協議最大的特點。本文就主要討論這兩個功能。

數據包重發

數據發送

丟包重發的前提是發送方能夠知道接收方是否成功的接收了消息。所以,在 TCP 協議中,接收端會給發送端返回一個通知,也叫作確認應答(ACK),這表示接收方已經收到了數據包。

根據上一節對 TCP 首部的分析得知,ACK 的值和下次發送數據包的序列號相等。因此 ACK 也可以理解為:“發送方,下次你從這個位置開始發送!”。下圖表示了數據發送與確認應答的過程:


ACK 確認

數據包和 ACK 應答都有可能丟失,在這種情況下,發送方如果在一段時間內沒有收到 ACK,就會重發數據:


未收到 ACK 時重發數據

即使網絡連接正常,由于延遲的存在,接收方也有可能收到重復的數據包,因此接收方通過 TCP 首部中的 SYN 判斷這個數據包是否曾經接收過。如果已經接收過,就會丟棄這個包。

重傳超時時間(RTO)

如果發送方等待一段時間后,還是沒有收到 ACK 確認,就會啟動超時重傳。這個等待的時間被稱為重傳超時時間(RTO,Retransmission TimeOut)。RTO 的值具體是多久呢?

首先,RTO 的值不是固定的,它是一個動態變化的時間。這個時間總是略大于連接往返時間(RTT,Round Trip Time)。這個設定可以這樣理解:“數據發送給對方,再返回到我這里,假設需要 10 秒,那我就等待 12秒,如果超過 12 秒,那估計就是回不來了。”

RTT 是動態變化的,因為誰也不知道網絡下一時刻是否擁堵。而當前的 RTO 需要根據未來的 RTT 估算得出。RTO 不能估算太大,否則會多等待太多時間;也不能太小,否則會因為網絡突然變慢而將不該重傳的數據進行重傳。

RTO 有自己的估算公式,可以保證即使 RTT 波動較大,它的變化也不會太劇烈。感興趣的讀者可以自行查閱相關資料。

TCP 窗口

按照之前的理論,在數據包發出后,直至 ACK 確認返回以前,發送端都無法發送數據,而且包的往返時間越長,網絡利用效率和通信性能就越低。前兩張圖片形象的解釋了這一點。

為了解決這個問題,TCP 使用了“窗口”這個概念。窗口具有大小,它表示無需等待確認應答就可以繼續發送數據包的最大數量。比如窗口大小為 4 時,數據發送的示意圖如下:


窗口大小為 4

不等確認就連續發送若干個數據包會不會有問題呢?我們首先來看數據包丟失問題。

我們知道 TCP 首部中的 ACK 字段表示接收方已經收到數據的最后位置。因此,接收方成功接收到了 1-1000 字節的數據后,它會發送一個 ACK = 1001 的確認包。假設 1001-2000 字節的數據包丟失了,由于窗口長度比較大,發送方會繼續發送 2001-3000 字節的數據包。接收端并不會返回這個數據包的確認,因為它最后收到的數據還是 1-1000 字節的數據包。

因此,接收端返回的數據包的 ACK 依然是 1001。這表示:“喂,發數據的,別往后發了,你第 1001 字節開始的數據還沒來呢”。可以想見,發送端以后每次發送數據包得到的確認中,ACK 的值都是 1001。當連續收到三次確認之后,發送方會意識到:“對方還沒有接收到數據,這個包需要重傳”。

因此,引入窗口的概念后,被發送的數據不能立刻丟棄,需要緩存起來以備將來需要重發。

利用窗口發送數據的過程可以用下圖表示:


快速重傳

如果是數據包沒有丟失,但是確認包丟失了呢?這就是窗口最擅長處理的問題了。假設發送發收到的確認包中的 ACK 第一次是 1001,第二次是 4001。那么我們完全可以相信中間的兩個包是成功被接收的。因為如果有沒接收到的包,接收方是不會增加 ACK 的。

在這種情況下,如果不使用窗口,發送方就需要重傳第二、三個數據包,但是有了窗口的概念后,發送方就省略了兩次重傳。因此使用窗口實際上可以理解為“空間換時間”。


某些確認包丟失時不用重發

流量控制

窗口大小

如果窗口過大,會導致接收方的緩存區數據溢出。這時候本該被接收的數據反而丟棄了,就會導致無意義的重傳。因此,窗口大小是一個可以改變的值,它由接收端主機控制,附加在 TCP 首部的“窗口大小”字段中。

慢啟動

在連接建立的初期,如果窗口比較大,發送方可能會突然發送大量數據,導致網絡癱瘓。因此,在通信一開始時,TCP 會通過慢啟動算法得出窗口的大小,對發送數據量進行控制。

流量控制是由發送方和接收方共同控制的。剛剛我們介紹了接收方會把自己能夠承受的最大窗口長度寫在 TCP 首部中,實際上在發送方這里,也存在流量控制,它叫擁塞窗口。TCP 協議中的窗口是指發送方窗口和接收方窗口的較小值。

慢啟動過程如下:

  1. 通信開始時,發送方的擁塞窗口大小為 1。每收到一個 ACK 確認后,擁塞窗口翻倍。
  2. 由于指數級增長非常快,很快地,就會出現確認包超時。
  3. 此時設置一個“慢啟動閾值”,它的值是當前擁塞窗口大小的一半。
  4. 同時將擁塞窗口大小設置為 1,重新進入慢啟動過程。
  5. 由于現在“慢啟動閾值”已經存在,當擁塞窗口大小達到閾值時,不再翻倍,而是線性增加。
  6. 隨著窗口大小不斷增加,可能收到三次重復確認應答,進入“快速重發”階段。
  7. 這時候,TCP 將“慢啟動閾值”設置為當前擁塞窗口大小的一半,再將擁塞窗口大小設置成閾值大小(也有說加 3)。
  8. 擁塞窗口又會線性增加,直至下一次出現三次重復確認應答或超時。

以上過程可以用下圖概括:


窗口大小變化示意圖

強烈建議讀者對照上述八個步驟理解這幅圖!



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

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

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

相關文章

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…

ApplePay集成教程

Apple Pay運行環境&#xff1a;iPhone6以上設備&#xff0c;操作系統最低iOS9.0以上&#xff0c;部分信息設置需要iOS9.2以上。目前還不支持企業證書添加。 環境搭建好后可以在模擬器上面運行&#xff0c;xcode7.2.1iPhone6SP9.2系統下&#xff0c;系統會綁定幾種虛擬的銀行卡…

Node — 第七天 (大事件項目接口實現一)

關于JS錯誤處理 node中和mysql中的錯誤處理 node和MySQL提供的方法&#xff0c;已經對錯誤信息進行了封裝&#xff0c;只需要使用 err.message 即可獲取到錯誤信息。 比如&#xff1a; const fs require(fs); // 讀取一個不存在的文件 fs.readFile(abcd.txt, (err, data) …

1.Consul 簡介和環境搭建

1.什么是 Consul Consul 是 service mesh(服務網格)的一個解決方案&#xff0c;它提供了諸如服務發現&#xff0c;配置和隔離等功能的一整套控制平面(control plane)。開發人員可以根據需要單獨使用這些功能點&#xff0c;也可以將他們整合成為一個完整的service mesh。Consul …