一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

電腦之家 - 專業計算機基礎知識與電腦技術學習網站
分類導航

路由器|交換機|網絡協議|網絡知識|

服務器之家 - 電腦之家 - 網絡技術 - 請求數據包從發送到接收,都經歷了什么?

請求數據包從發送到接收,都經歷了什么?

2021-10-08 23:23SH的全棧筆記 網絡技術

這篇文章不會涉及到上面提到的什么各種狀態的變化,包內的標志位是什么,而是會更加關注于底層的東西,也就是上面那些發來發去的數據包是如何發送出去的。

請求數據包從發送到接收,都經歷了什么?

之前講了「從輸入 URL 再到瀏覽器成功看到界面」中的域名是如何變成 IP 地址的,了解了 DNS 相關的東西。這篇文章就聊聊發生在 DNS 解析之后的操作——建立連接。也就是我們常說的三次握手

看到三次握手你可能會說,這不是面試都被問爛了的題嗎?

三次握手不就是:

  1. 服務器開始為 CLOSE 狀態,然后監聽某個端口,此時服務器會進入 LISTEN 狀態
  2. 客戶端最初也是 CLOSE 狀態,客戶端會向服務器發送一個帶 SYN 標志位的數據包,主動發起連接。此時客戶端會變成 SYN-SENT 狀態
  3. 服務器接收到客戶端的數據包之后,通過標志位判斷出了客戶端想要建立連接。然后返回一個 SYN 和 ACK ,此時服務器的狀態變為了 SYN-RCVD
  4. 客戶端收到了服務器的 ACK 之后,會回一個 ACK 給服務器,回完這個 ACK 之后,服務器的狀態就變為了 ESTABLISH
  5. 服務器收到了客戶端回復的 ACK 之后,服務器的狀態也變成了 ESTABLISH

這不就完了嗎?還有什么好聊的?

這篇文章不會涉及到上面提到的什么各種狀態的變化,包內的標志位是什么,而是會更加關注于底層的東西,也就是上面那些發來發去的數據包是如何發送出去的。

其實不僅僅是建立連接時的三次握手,像瀏覽器中調用的很多 HTTP 接口,都會和服務器進行通信。

那這些個請求到底都是怎么發送給服務器的呢?

這還用問?不就是發個 HTTP 請求就過去了嗎?

當然,這個答案可能是很多不了解網絡的人可能會說出的答案。

其實更具體、更準確的說法是通過協議棧和網卡發送出去的。

其中,協議棧負責對數據進行打包,打包完成之后就由網卡將數據轉換成電信號,通過光纖發送出去了。

請求數據包從發送到接收,都經歷了什么?

網卡自不必說,用來和其他的計算機進行通訊的硬件,我們常說的 MAC(Medium Access Control) 地址,其實就是網卡的編號,從其被生產出來的那一刻就被確定的一個唯一編號。MAC 地址長為 48 個比特,也就是 6 個字節,用十六進制進行表示。

當我們知道了和我們通信的 IP 地址之后,就可以委托操作系統中的協議棧將來來自應用程序的數據,打包成數據包然后發送出去。那協議棧,具體是啥呢?協議棧其實是一系列網絡協議的總和,例如:

  • TCP
  • UDP
  • IP

不同的應用程序在進行數據傳輸的時候,可能會選擇不同的協議。例如我們使用的瀏覽器就是使用的 TCP 協議,而像之前講過的 DNS 解析就用的 UDP 協議。

那數據在協議棧中到底經歷了什么?才變成了一個一個的數據包?

就拿我們向服務器發送一個 HTTP 請求作為例子,我們知道 HTTP 請求中有:

  • 請求行
  • 請求頭
  • 請求體

HTTP 是屬于應用層的協議,而應用層還有很多其他的協議,每個協議所涉及到的數據也都不同,協議棧要怎么去兼容不同協議之間的數據呢?

答案是不做兼容。對于協議棧來說,所有的數據都只不過是一堆二進制序列。

請求數據包從發送到接收,都經歷了什么?

那協議棧收到了這一堆二進制序列之后是不是就直接交給網卡發送了呢?

我都這么問了,那顯然不是了...

其實協議棧在收到數據之后并不會馬上就會就發送出去,而是會先寫入位于內存的 Buffer 中。那為啥不直接發出呢?

其實很簡單,假設你現在正在公交車的起始站,你覺得公交車會來一個人就立馬發車嗎?

顯然不是,它會等一段時間,有更多的乘客上車之后再發車。但是它又不能等太長的時間,不然后續站臺的乘客就會等的很久。

協議棧之所以不立即發出去,其實也是同樣的道理。其實這背后無非基礎兩種考慮:

  1. 數據的長度
  2. 等待的時間

應用層的程序發送過來的數據可能長度都不太一樣,有的可能一個字節一個字節的發, 有的可能一次性就傳入所有的數據。

如果收到數據就發送出去,會導致在網絡中傳輸著很多小包,而這會降低網絡傳輸的效率。

請求數據包從發送到接收,都經歷了什么?

所以,協議棧在收到數據之后會等待一段時間,等數據達到一定量之后,再執行發送操作。

請求數據包從發送到接收,都經歷了什么?

但是,協議棧又不能等的太久是吧?等太久了你讓正在電腦面前操作的用戶情何以堪,這種發送延遲會讓用戶體驗刷刷的往下掉。

但是吧,想做到對這兩者的平衡卻不是一件簡單的事。數據包太短,降低網絡傳輸效率,等待太長時間,又會造成發送延遲。所以協議棧索性就把控制權交給了應用程序。

應用程序可以自己控制到底采取哪種措施,例如我們常用的瀏覽器,因為和用戶實時的在進行交互,用戶對整個頁面的響應速度也相當敏感,所以一般都會采用直接發送數據的方式,即使其數據并沒有達到「一定的量」

這一個「一定的量」到底是啥?

的確,上面都只說一定的量、一定的量,那這個量到底是多少?

要了解這個我們需要知道兩個參數,分別是:

  1. MTU(Maximum Transmission Unit)最大傳輸單元
  2. MSS(Maximum Segment Size)最大分段大小

MTU 其實就代表了上面途中數據包的最大長度,一般來說是 1500 字節。而我們需要知道數據包是由以下部分組成的:

  1. 各種頭部信息
  2. 真實數據

而從 MTU 中減去各種頭部數據的大小,剩下的就是 MSS 了,也就是實際的數據。

請求數據包從發送到接收,都經歷了什么?

知道了數據包的組成和 MTU、MSS 的概念之后,我們就可以繼續接下來的步驟了。某次發送的數據,沒有超過 MSS 還好,就可以直接發送出去了。

那如果超過了 MSS 咋辦?例如我發這篇文章時所發請求的數據長度就可能超過 MSS 。

請求數據包從發送到接收,都經歷了什么?

過長數據包拆分

此時就需要對數據進行拆分,按照 MSS 的長度為單位進行拆分,將拆出來的數據分別裝進不同的數據包中。拆分好之后,就可以發送給目標服務器了。

TCP 會確保通信的服務器能夠收到數據包。傳輸時對每個字節都進行了編號,舉個例子,假設此次傳輸的數據是 1 - 1000 字節,然后服務器回的 ACK 就會是 1001,這就代表沒有丟包。

這些發送過的包都會暫存在 Buffer 中,如果傳輸的過程中出錯,則可以進行重發的補償措施。這也是為什么在數據鏈路層(例如網卡、路由器、集線器)等等都沒有補償機制,它們一旦檢測到錯誤會直接將包丟棄。然后由傳輸層重發就好。

那要是網絡很擁堵,服務器一直沒有返回怎么辦?

在服務器端,我們去和其他第三發進行交互時,是不是都會設定一個超時的時間?如果不設置超時時間那難道一直在這等下去嗎?

TCP 也同理。客戶端在等待服務器響應時,會有一個時間叫 ACK 等待時間,其實也是超時時間。

當網絡發生擁堵時,其實你完全也可以把網絡擁堵理解成路上堵車。此時,ACK 的返回就會變慢。如果返回時間長到了讓客戶端認為服務器沒有收到,就有可能會重發。

并且有可能剛剛重發完,ACK 就到了。雖然服務器端可以通過序號來對包進行判重,不會造成錯誤,但是這種沒有意義的重復包,在本身網絡負擔已經很重的情況下,你還往里懟重復的無用的數據包,這不是扯淡嗎?這明顯不行的。

那怎么避免上面的這個情況呢?答案很簡單,稍微延長一點 ACK等待時間,這樣一來就能一定程度上避免上述的問題。但是用屁股想想應該也知道,這個時間肯定不是越長越好,再長用戶那又該等爆炸了。

除了網絡波動會影響到 ACK 的返回時間,通信的物理距離也是一個影響的因素。說白了就是這玩意兒不可能設置一個固定的時間。所以,實際上,這個等待時間是動態調整的,這次稍微返回慢了點,那我下次就稍微延長一點等待時間。返回 ACK 的速度如果很給力,那么就會相應的減少等待。

上面的概念也有一個大家很熟悉的名字,叫——超時重傳。

我們來設想一個更加極端的情況,假設你們通信的網線被挖斷了,甚至機房起火了,這個時候無論你重發多少次都沒用。那 TCP 不就一直無限循環的把請求發下去了?

當然 TCP 設計時也考慮到了這種情況,其在重傳幾次無效之后,就會強制中斷通信,并拋出錯誤給應用程序。

問題又來了,客戶端在向服務器發送數據包之后,等待 ACK 的過程中,真的就只是等 ACK,其他的什么也不做嗎?

當然不是,這樣極其的浪費資源,降低通信效率。發送完一個數據包之后,不用等待 ACK 的返回,會直接繼續發送下一個包,這就是滑動窗口。

但是這樣會有一個問題,應用程序發送包發送的過于頻繁,導致服務器接收不過來了。

因為剛剛說過,應用程序發送的時候,會將發送過的數據存儲在 buffer 中。而對于接收方也是一樣的,接收方收到消息之后,會將數據存儲在 Buffer 中,然后在 Buffer 中對收到的數據進行重組,還原成最初的應用程序發送的數據。

但是如果發送的數據太快,超過了重組的速度,緩沖區就會被填滿。而緩沖區一旦被填滿,后續的數據就無法再接收了,然后丟包就出現了。

那 TCP 是如何解決這個問題的呢?答案是 流量控制。為了防止傳輸方發送的過快直接造成丟包,繼而觸發上面的超時重傳機制,根據接收方的接受能力,來決定發送方的傳輸速度,這個機制就是流量控制。

該機制作用于接受方。在TCP報文頭部中會用一個16位的字段來表示窗口大小,非常重要的調優參數。這個數字越大,則說明接收方的緩沖區越大,能夠接收更多的數據。接收方會在確認應答的時候,將自己的剩余窗口大小寫入,隨ACK一起發送給發送方。

請求數據包從發送到接收,都經歷了什么?

TCP流量控制

如果發送方接收到的大小為0,那么此時就會停止發送數據。這樣會有一個問題,如果下一個應答(也就是窗口大小不為0)在過程中丟了,那么發送方就會進入死鎖,相互等待。所以發送方會定期的向接收方發送窗口探測的數據段。

好了,關于數據包的發送就介紹到這里。之后有機會再聊聊 TCP 的擁塞控制相關的東西。

原文鏈接:https://mp.weixin.qq.com/s/JYPhwwuBPPHH8GgJtoCyug

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青青青国产成人久久111网站 | 欧美视频网址 | 亚洲精品97福利在线 | 校花被吃奶还摸下面 | 久久中文字幕无线观看 | 成人久久18免费网站入口 | 四虎国产视频 | 国产精品视频色拍拍 | 国产亚洲精品一区二区在线观看 | 人禽l交免费视频观看+视频 | 欧美激情影音先锋 | 麻豆视频入口 | 午夜性爽视频男人的天堂在线 | 97青草香蕉依人在线播放 | 精品久久亚洲 | 国产高清自拍 | 动漫美女被吸乳 | 末发育xxxxx仙踪林 | 久久免费国产视频 | 亚洲精品91 | 国产成人福利美女观看视频 | 国内剧情麻豆 | 1377大但人文艺术包子铺 | 欧美整片完整片视频在线 | 日韩精品久久不卡中文字幕 | 小货SAO边洗澡边CAO你动漫 | 亚洲2017久无码 | 久久五月综合婷婷中文云霸高清 | 久久精品观看影院2828 | yy6080午夜国产免费福利 | 办公室操秘书 | 国产在线观看精品香蕉v区 国产在线观看a | 亚洲久草视频 | 亚洲欧美自偷自拍另类小说 | 日韩二三区 | 国产成人性色视频 | 国产欧美一区二区精品久久久 | 天天综合亚洲 | 国产精品视频一区二区三区 | 高考录取率1977-2021 | 99精品国产久热在线观看66 |