當你輸入網址,小手一點,然後發生了什麼?

来源:https://www.cnblogs.com/huaweiyun/archive/2023/01/12/17046803.html
-Advertisement-
Play Games

摘要:輸入網址並點回車,後臺到底發生了什麼。透析 HTTP 協議與 TCP 連接之間的千絲萬縷的關係。掌握為何是三次握手四次揮手?time_wait 存在的意義是什麼?全面圖解重點問題,再也不用擔心面試問這個問題。 本文分享自華為雲社區《輸入網址,小手一點,後面到底發生了什麼?》,作者:龍哥手記。 ...


摘要:輸入網址並點回車,後臺到底發生了什麼。透析 HTTP 協議與 TCP 連接之間的千絲萬縷的關係。掌握為何是三次握手四次揮手?time_wait 存在的意義是什麼?全面圖解重點問題,再也不用擔心面試問這個問題。

本文分享自華為雲社區《輸入網址,小手一點,後面到底發生了什麼?》,作者:龍哥手記。

輸入網址並點回車,後臺到底發生了什麼。透析 HTTP 協議與 TCP 連接之間的千絲萬縷的關係。掌握為何是三次握手四次揮手?time_wait 存在的意義是什麼?全面圖解重點問題,再也不用擔心面試問這個問題。

大致流程

  • URL 解析,解析 http 協議、埠、資源地址。
  • DNS 查詢:首先查詢本地 host,再訪問 DNS 伺服器將 功能變數名稱解析成 ip 地址。
  • 建立 TCP 連接。
  • 伺服器收到請求後處理,並且構造響應返回給客戶端。
  • 客戶端接收 HTTP 報文響應。
  • 渲染頁面,最後有可能會四次揮手斷開連接,也可能不會而是復用連接。

重點來了:

  • 如何理解 TCP 的三次握手與四次揮手?每次握手客戶端與服務端是怎樣的狀態?
  • 為何揮手會出現 2MSL,遇到大量 Socket 處在 TIME_WAIT 或者 CLOSE_WAIT 狀態是什麼問題?
  • 三次握手與四次揮手的過程是怎樣的?
  • HTTP 的報文格式又是怎樣的?

URL 解析

url 遵守的規則是這個樣子

scheme://host.domain:port/path/filename

每個名詞的含義如下解釋:

  • scheme 定義應用層協議類型,比如 http、https、 ftp 等;
  • host 定義域主機(http 的預設主機是 www);
  • domain 定義網際網路功能變數名稱,比如 segmentfault.com;
  • port 主機的埠,http 預設是 80, https 預設是 443;
  • path 伺服器上的資源路徑;
  • filename - 定義文檔/資源的名稱;

DNS 查詢

瀏覽器不能直接通過功能變數名稱找到伺服器,只能通過 IP 地址。

那瀏覽器是如何通過功能變數名稱查詢到我們輸入的 url 對應的 IP 呢?

  • 瀏覽器緩存:按照一定頻率緩存 DNS 數據。
  • 操作系統緩存:如果瀏覽器緩存找不到記錄則去操作系統中找。
  • 路由緩存:路由器 DNS 緩存。
  • ISP 的 DNS 伺服器:ISP 是互聯網服務提供商(Internet Service Provider)的簡稱,ISP 有專門的 DNS 伺服器應對 DNS 查詢請求。
  • 根伺服器:ISP 的 DNS 伺服器還找不到的話,它就會向根伺服器發出請求,進行遞歸查詢(DNS 伺服器先問根功能變數名稱伺服器.com 功能變數名稱伺服器的 IP 地址,然後再問 .baidu 功能變數名稱伺服器,依次類推)

TCP 連接建立與斷開

通過功能變數名稱解析出 IP 地址以後就要建立 TCP/IP 連接了。

TCP/IP 分為四層,每一層都會加上一個頭部再發送給下一層。到了接收方後,對應的每一層則把對應層的頭部解析拆除,丟上上一層,跟發送端的過程反過來。

TCP/IP四層模型

應用層:發送 HTTP 請求

瀏覽器從地址欄得到伺服器 IP,接著構造一個 HTTP 報文,其中包括:

  • 請求行包含請求方法、URL、協議版本
  • 請求報頭(Request Header):由 “關鍵字: 值”對組成,每行一對,關鍵字與值使用英文 “:” 分割
  • 請求體:請求參數,並不是所有的請求都有請求參數。一般 get 參數 的格式 name=tom&password=1234&realName=tomson,也可以將參數放在 body 裡面。

傳輸層:TCP 傳輸報文

在傳輸報文之前會先建立 TCP/IP 連接,也就是後面我們要說的三次握手。

在這一層解決了數據可靠傳輸、及流量控制、擁塞控制。

可靠傳輸

對於發送方發送的數據,接收方在接受到數據之後必須要給予確認,確認它收到了數據。如果在規定時間內,沒有給予確認則意味著接收方沒有接受到數據,然後發送方對數據進行重發。

TCP的可靠傳輸是通過確認和超時重傳的機制來實現的,而確認和超時重傳的具體的實現是通過以位元組為單位的滑動視窗機制來完成。

TCP擁塞控制

TCP協議通過慢啟動機制、擁塞避免機制、加速遞減機制、快重傳和快恢復機制來共同實現擁塞控制。

流量控制

採用通知視窗實現對發送端的流量控制,通知視窗大小的單位是位元組。TCP通過在TCP數據段首部的視窗欄位中填入當前設定的接收視窗(即通知視窗)的大小,用來告知對方 '我方當前的接收視窗大小',以實現流量控制。

通信雙方的發送視窗大小由雙方在連接建立的時候商定,在通信過程,雙方可以動態地根據自己的情況調整對方的發送視窗大小。

網路層:IP 協議查詢 MAC 地址

將數據段打包,並加入源及目標的 IP 地址,並且負責尋找傳輸路線。判斷目標地址是否與當前地址處於同一網路中,是的話直接根據 Mac 地址發送,否則使用路由表查找下一跳地址,以及使用 ARP 協議查詢它的 Mac 地址。

鏈路層:乙太網協議

根據乙太網協議將數據分為以“幀”為單位的數據包,每一幀分為兩個部分:

  • 標頭:數據包的發送者、接受者、數據類型
  • 數據:數據包具體內容

Mac 地址

乙太網規定了連入網路的所有設備都必須具備“網卡”介面,數據包都是從一塊網卡傳遞到另一塊網卡,網卡的地址就是 Mac 地址。每一個 Mac 地址都是獨一無二的,具備了一對一的能力。

三次握手

在傳輸層傳輸數據之前需要建立連接,也就是三次握手創建可靠連接。

三次握手

首先建立鏈接前需要 Server 端先監聽埠,因此 Server 端建立鏈接前的初始狀態就是 LISTEN 狀態,這時 Client 端準備建立鏈接,先發送一個 SYN 同步包,發送完同步包後,Client 端的鏈接狀態變成了 SYN_SENT 狀態。Server 端收到 SYN 後,同意建立鏈接,會向 Client 端回覆一個 ACK。

由於 TCP 是雙工傳輸,Server 端也會同時向 Client 端發送一個 SYN,申請 Server 向 Client 方向建立鏈接。發送完 ACK 和 SYN 後,Server 端的鏈接狀態就變成了 SYN_RCVD。

Client 收到 Server 的 ACK 後,Client 端的鏈接狀態就變成了 ESTABLISHED 狀態,同時,Client 向 Server 端發送 ACK,回覆 Server 端的 SYN 請求。

Server 端收到 Client 端的 ACK 後,Server 端的鏈接狀態也就變成了的 ESTABLISHED 狀態,此時建連完成,雙方隨時可以進行數據傳輸。

在面試時需要明白三次握手是為了建立雙向的鏈接,需要記住 Client 端和 Server 端的鏈接狀態變化。另外回答建連的問題時,可以提到 SYN 洪水攻擊發生的原因,就是 Server 端收到 Client 端的 SYN 請求後,發送了 ACK 和 SYN,但是 Client 端不進行回覆,導致 Server 端大量的鏈接處在 SYN_RCVD 狀態,進而影響其他正常請求的建連。可以設置 tcp_synack_retries = 0 加快半鏈接的回收速度,或者調大 tcp_max_syn_backlog 來應對少量的 SYN 洪水攻擊

四次揮手

我們只要關註 80 埠與 13743 埠建立的連接斷開過程,瀏覽器通過 13747 埠發送 [FIN, ACK] 這裡是不是跟很多網上看到的不一樣?

  1. 其實是客戶端在發送 [FIN] 報文的時候順帶發了一個 [ACK] 確認上次傳輸確認。
  2. 接著服務端通過 80 埠響應了 [ACK] ,然後立馬響應 [FIN, ACK] 表示數據傳輸完了,可以關閉連接。
  3. 最後瀏覽器通過 13743 埠 發送 [ACK] 包給服務端,客服端與服務端連接就關閉了。

具體流程如下圖抓包所示:

三次握手與四次揮手

TCP 連接與斷開

客戶端:

  • SYN_SENT - 客戶端發起第 1 次握手後,連接狀態為 SYN_SENT ,等待服務端內核進行應答,如果服務端來不及處理(例如服務端的 backlog 隊列已滿)就可以看到這種狀態的連接。
  • ESTABLISHED - 表示連接處於正常狀態,可以進行數據傳送。客戶端收到伺服器回覆的 SYN+ACK 後,對服務端的 SYN 單獨回覆(第 3 次握手),連接建立完成,進入 ESTABLISHED 狀態。服務端程式收到第 3 次握手包後,也進入 ESTABLISHED 狀態。
  • FIN_WAIT_1 - 客戶端發送了關閉連接的 FIN 報文後,等待服務端回覆 ACK 確認。
  • FIN_WAIT_2 - 表示我方已關閉連接,正在等待服務端關閉。客戶端發了關閉連接的 FIN 報文後,伺服器發回 ACK 應答,但是沒進行關閉,就會處於這種狀態。
  • TIME_WAIT - 雙方都正常關閉連接後,客戶端會維持 TIME_WAIT 一段時間,以確保最後一個 ACK 能成功發送到伺服器端。停留時長為 2 倍的 MSL (報文最大生存時間),Linux 下大約是 60 秒。所以在一個頻繁建立短連接的伺服器上通常可以看到成千上萬的 TIME_WAIT 連接。

服務端:

  • LISTEN - 表示當前程式正在監聽某個埠時。
  • SYN_RCVD - 服務端收到第 1 次握手後,進入 SYN_RCVD 狀態,並回覆一個 SYN+ACK(第 2 次握手),再等待對方確認。
  • ESTABLISHED - 表示連接處於正常狀態,可以進行數據傳送。完成 TCP3 次握手後,連接建立完成,進入 ESTABLISHED 狀態。
  • CLOSE_WAIT - 表示客戶端已經關閉連接,但是本地還沒關閉,正在等待本地關閉。有時客戶端程式已經退出了,但服務端程式由於異常或 BUG 沒有調用 close()函數對連接進行關閉,那在伺服器這個連接就會一直處於 CLOSE_WAIT 狀態,而在客戶機已經不存在這個連接了。
  • LAST_ACK - 表示正在等待客戶端對服務端的關閉請求進行最終確認。

TIME_WAIT 狀態存在的理由:

劃重點了

  • 可靠地實現 TCP 全雙工連接的終止 在進行關閉連接四路握手協議時,最後的 ACK 是由主動關閉端發出的,如果這個最終的 ACK 丟失,伺服器將重發最終的 FIN,因此客戶端必須維護狀態信息允 許它重發最終的 ACK。如 果不維持這個狀態信息,那麼客戶端將響應 RST 分節,伺服器將此分節解釋成一個錯誤( 在 java 中會拋出 connection reset 的 SocketException)。因而,要實現 TCP 全雙工連接的正常終 止,必須處理終止序列四個分節中任何一個分節的丟失情況,主動關閉 的客戶端必須維持狀 態信息進入 TIME_WAIT 狀態。
  • 允許老的重覆分節在網路中消逝 TCP 分節可能由於路由器異常而“迷途”,在迷途期間,TCP 發送端可能因確認超時而重發這個 分節,迷途的分節在路由器修複後也會被送到最終目的地,這個 原來的迷途分節就稱為 lost duplicate。在關閉一個 TCP 連接後,馬上又重新建立起一個相同的 IP 地址和埠之間的 TCP 連接,後一個連接被稱為前一個連接的化身 ( incarnation),那麼有可能出現這種情況,前一 個連接的迷途重覆分組在前一個連接終止後出現,從而被誤解成從屬於新的化身。為了避免 這個情 況,TCP 不允許處於 TIME_WAIT 狀態的連接啟動一個新的化身,因為 TIME_WAIT 狀 態持續 2MSL,就可以保證當成功建立一個 TCP 連接的時 候,來自連接先前化身的重覆分組已 經在網路中消逝。

另外回答斷鏈的問題時,可以提到實際應用中有可能遇到大量 Socket 處在 TIME_WAIT 或者 CLOSE_WAIT 狀態的問題。一般開啟 tcp_tw_reuse 和 tcp_tw_recycle 能夠加快 TIME-WAIT 的 Sockets 回收;而大量 CLOSE_WAIT 可能是被動關閉的一方存在代碼 bug,沒有正確關閉鏈接導致的。

簡單地說就是

  1. 保證 TCP 協議的全雙工連接能夠可靠關閉;
  2. 保證這次連接的重覆數據段從網路中消失,防止埠被重用時可能產生數據混淆;

 

點擊關註,第一時間瞭解華為雲新鮮技術~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 參考sapui5 TreeTable控制項的示例,我們發現所有的可展開列(即所謂的hierarchical data column)預設都在第一列,而且API中並沒有給出對應的屬性或方法來重新指定可展開列在table中的位置。 我們可以編寫一個自定義控制項,使其繼承sapui5的TreeTable控制項, ...
  • AngularJS——初識AngularJS AngularJS是什麼 AngularJS是Google開源的一款前端JS結構化框架,它通過對前端開發進行分層,極好地規範了前端開發的風格——它將前端開發分為Controller層、Service層、DAO層和Model層。其中,Model對象與HTM ...
  • JavaScript 面向切麵編程 (AOP) 是一種編程思想和實現方式,它將一些關註點(例如日誌記錄、安全性檢查、性能監控等)從主題對象中分離出來,通過“橫切關註點”的方式在程式中動態地織入這些關註點。這樣可以避免在主題對象中嵌入大量的關註點代碼,使得代碼更加簡潔和可維護。 ...
  • CSS Grid 佈局是一種二維佈局方式,可以將頁面分成行和列,併在其中放置元素。使用 Grid 佈局時,需要定義網格容器和網格項目。 ...
  • Axios 1.基本說明 Axios是一個基於promise的網路請求庫,作用於node.js和瀏覽器中。它是 isomorphic 的 (即同一套代碼可以運行在瀏覽器和node.js中)。在服務端它使用原生node.js http 模塊, 而在客戶端 (瀏覽端) 則使用XMLHttpRequest ...
  • JavaScript 是一種基於原型繼承的語言。在 JavaScript 中,對象是通過原型鏈來繼承屬性和方法的。 一、原型 每一個對象都有一個 proto 屬性,該屬性指向該對象的原型。原型本質上也是一個對象,所有的對象都擁有一個原型,除了 Object.prototype。 JavaScript ...
  • 著意登樓瞻玉兔,何人張幕遮銀闕?又到了一年一度的網頁小掛件環節,以往我們都是集成別人開源的組件,但所謂熟讀唐詩三百首,不會做詩也會吟,熟讀了別人的東西,做幾首打油詩也是可以的,但若不能自出機抒,卻也成不了大事,所以本次我們從零開始製作屬於自己的網頁小掛件,博君一曬。 玉兔主題元素繪製 成本最低的繪製 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、audio標簽的使用 1、Audio 對象屬性 2、對象方法 二、效果 效果如下: 三、代碼 代碼如下: MusicPlayer.vue <template> <div class="music"> <!-- 占位 --> <div ...
一周排行
    -Advertisement-
    Play Games
  • 隨著Aspire發佈preview5的發佈,Microsoft.Extensions.ServiceDiscovery隨之更新, 服務註冊發現這個屬於老掉牙的話題解決什麼問題就不贅述了,這裡主要講講Microsoft.Extensions.ServiceDiscovery(preview5)以及如何 ...
  • 概述:通過使用`SemaphoreSlim`,可以簡單而有效地限制非同步HTTP請求的併發量,確保在任何給定時間內不超過20個網頁同時下載。`ParallelOptions`不適用於非同步操作,但可考慮使用`Parallel.ForEach`,儘管在非同步場景中謹慎使用。 對於併發非同步 I/O 操作的數量 ...
  • 1.Linux上安裝Docken 伺服器系統版本以及內核版本:cat /etc/redhat-release 查看伺服器內核版本:uname -r 安裝依賴包:yum install -y yum-utils device-mapper-persistent-data lvm2 設置阿裡雲鏡像源:y ...
  • 概述:WPF界面綁定和渲染大量數據可能導致性能問題。通過啟用UI虛擬化、非同步載入和數據分頁,可以有效提高界面響應性能。以下是簡單示例演示這些優化方法。 在WPF中,當你嘗試綁定和渲染大量的數據項時,性能問題可能出現。以下是一些可能導致性能慢的原因以及優化方法: UI 虛擬化: WPF提供了虛擬化技術 ...
  • 引言 上一章節介紹了 TDD 的三大法則,今天我們講一下在單元測試中模擬對象的使用。 Fake Fake - Fake 是一個通用術語,可用於描述 stub或 mock 對象。 它是 stub 還是 mock 取決於使用它的上下文。 也就是說,Fake 可以是 stub 或 mock Mock - ...
  • 為.net6在CentOS7上面做準備,先在vmware虛擬機安裝CentOS 7.9 新建CentOS764位的系統 因為CentOS8不更新了,所以安裝7;簡單就一筆帶過了 選擇下載好的操作系統的iso文件,下載地址https://mirrors.aliyun.com/centos/7.9.20 ...
  • 經過前面幾篇的學習,我們瞭解到指令的大概分類,如:參數載入指令,該載入指令以 Ld 開頭,將參數載入到棧中,以便於後續執行操作命令。參數存儲指令,其指令以 St 開頭,將棧中的數據,存儲到指定的變數中,以方便後續使用。創建實例指令,其指令以 New 開頭,用於在運行時動態生成並初始化對象。方法調用指... ...
  • LiteDB 是一個輕量級的嵌入式 NoSQL 資料庫,其設計理念與 MongoDB 類似,但它是完全使用 C# 開發的,因此與 C# 應用程式的集成非常順暢。與 SQLite 相比,LiteDB 提供了 NoSQL(即鍵值對)的數據存儲方式,並且是一個開源且免費的項目。它適用於桌面、移動以及 We ...
  • 1 開源解析和拆分文檔 第三方的工具去對文件解析拆分,去將我們的文件內容給提取出來,並將我們的文檔內容去拆分成一個小的chunk。常見的PDF word mark down, JSON、HTML。都可以有很好的一些模塊去把這些文件去進行一個東西去提取。 優勢 支持豐富的文檔類型 每種文檔多樣化選擇 ...
  • OOM是什麼?英文全稱為 OutOfMemoryError(記憶體溢出錯誤)。當程式發生OOM時,如何去定位導致異常的代碼還是挺麻煩的。 要檢查OOM發生的原因,首先需要瞭解各種OOM情況下會報的異常信息。這樣能縮小排查範圍,再結合異常堆棧、heapDump文件、JVM分析工具和業務代碼來判斷具體是哪 ...