Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产91在线播放,国产亚洲精品hd网站,最近中文字幕完整版视频在线看

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          在瀏覽器輸入 URL 回車之后發生了什么

          在瀏覽器輸入 URL 回車之后發生了什么

          這個問題已經是老生常談了,更是經常被作為面試的壓軸題出現,網上也有很多文章,但最近閑的無聊,然后就自己做了一篇筆記,感覺比之前理解更透徹了。

          這篇筆記是我這兩天看了數十篇文章總結出來的,所以相對全面一點,但由于我是做前端的,所以會比較重點分析瀏覽器渲染頁面那一部分,至于其他部分我會羅列出關鍵詞,感興趣的可以自行查閱.

          注意:本文的步驟是建立在,請求的是一個簡單的 HTTP 請求,沒有 HTTPS、HTTP2、最簡單的 DNS、沒有代理、并且服務器沒有任何問題的基礎上,盡管這是不切實際的。

          大致流程

          1. URL 解析
          2. DNS 查詢
          3. TCP 連接
          4. 處理請求
          5. 接受響應
          6. 渲染頁面

          一、URL 解析

          地址解析:

          首先判斷你輸入的是一個合法的 URL 還是一個待搜索的關鍵詞,并且根據你輸入的內容進行自動完成、字符編碼等操作。

          HSTS

          由于安全隱患,會使用 HSTS 強制客戶端使用 HTTPS 訪問頁面。詳見:你所不知道的 HSTS[1]

          其他操作

          瀏覽器還會進行一些額外的操作,比如安全檢查、訪問限制(之前國產瀏覽器限制 996.icu)。

          檢查緩存

          二、DNS 查詢

          基本步驟

          1. 瀏覽器緩存

          瀏覽器會先檢查是否在緩存中,沒有則調用系統庫函數進行查詢。

          2. 操作系統緩存

          操作系統也有自己的 DNS緩存,但在這之前,會向檢查域名是否存在本地的 Hosts 文件里,沒有則向 DNS 服務器發送查詢請求。

          3. 路由器緩存

          路由器也有自己的緩存。

          4. ISP DNS 緩存

          ISP DNS 就是在客戶端電腦上設置的首選 DNS 服務器,它們在大多數情況下都會有緩存。

          根域名服務器查詢

          在前面所有步驟沒有緩存的情況下,本地 DNS 服務器會將請求轉發到互聯網上的根域,下面這個圖很好的詮釋了整個流程:

          根域名服務器(維基百科)

          需要注意的點

          1. 遞歸方式:一路查下去中間不返回,得到最終結果才返回信息(瀏覽器到本地DNS服務器的過程)
          2. 迭代方式,就是本地DNS服務器到根域名服務器查詢的方式。
          3. 什么是 DNS 劫持
          4. 前端 dns-prefetch 優化

          三、TCP 連接

          TCP/IP 分為四層,在發送數據時,每層都要對數據進行封裝:

          1. 應用層:發送 HTTP 請求

          在前面的步驟我們已經得到服務器的 IP 地址,瀏覽器會開始構造一個 HTTP 報文,其中包括:

          • 請求報頭(Request Header):請求方法、目標地址、遵循的協議等等
          • 請求主體(其他參數)

          其中需要注意的點:

          • 瀏覽器只能發送 GET、POST 方法,而打開網頁使用的是 GET 方法

          2. 傳輸層:TCP 傳輸報文

          傳輸層會發起一條到達服務器的 TCP 連接,為了方便傳輸,會對數據進行分割(以報文段為單位),并標記編號,方便服務器接受時能夠準確地還原報文信息。

          在建立連接前,會先進行 TCP 三次握手。

          關于 TCP/IP 三次握手,網上已經有很多段子和圖片生動地描述了。相關知識點:
          • SYN 泛洪攻擊

          3. 網絡層:IP協議查詢Mac地址

          將數據段打包,并加入源及目標的IP地址,并且負責尋找傳輸路線。

          判斷目標地址是否與當前地址處于同一網絡中,是的話直接根據 Mac 地址發送,否則使用路由表查找下一跳地址,以及使用 ARP 協議查詢它的 Mac 地址。

          注意:在 OSI 參考模型中 ARP 協議位于鏈路層,但在 TCP/IP 中,它位于網絡層。

          4. 鏈路層:以太網協議

          以太網協議

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

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

          Mac 地址

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

          廣播

          發送數據的方法很原始,直接把數據通過 ARP 協議,向本網絡的所有機器發送,接收方根據標頭信息與自身 Mac 地址比較,一致就接受,否則丟棄。

          注意:接收方回應是單播。

          相關知識點:
          • ARP 攻擊

          服務器接受請求

          接受過程就是把以上步驟逆轉過來,參見上圖。

          四、服務器處理請求

          大致流程

          HTTPD

          最常見的 HTTPD 有 Linux 上常用的 Apache 和 Nginx,以及 Windows 上的 IIS。

          它會監聽得到的請求,然后開啟一個子進程去處理這個請求。

          處理請求

          接受 TCP 報文后,會對連接進行處理,對HTTP協議進行解析(請求方法、域名、路徑等),并且進行一些驗證:

          • 驗證是否配置虛擬主機
          • 驗證虛擬主機是否接受此方法
          • 驗證該用戶可以使用該方法(根據 IP 地址、身份信息等)

          重定向

          假如服務器配置了 HTTP 重定向,就會返回一個 301永久重定向響應,瀏覽器就會根據響應,重新發送 HTTP 請求(重新執行上面的過程)。

          關于更多:詳見這篇文章[2]

          URL 重寫

          然后會查看 URL 重寫規則,如果請求的文件是真實存在的,比如圖片、html、css、js文件等,則會直接把這個文件返回。

          否則服務器會按照規則把請求重寫到 一個 REST 風格的 URL 上。

          然后根據動態語言的腳本,來決定調用什么類型的動態文件解釋器來處理這個請求。

          以 PHP 語言的 MVC 框架舉例,它首先會初始化一些環境的參數,根據 URL 由上到下地去匹配路由,然后讓路由所定義的方法去處理請求。

          五、瀏覽器接受響應

          瀏覽器接收到來自服務器的響應資源后,會對資源進行分析。

          首先查看 Response header,根據不同狀態碼做不同的事(比如上面提到的重定向)。

          如果響應資源進行了壓縮(比如 gzip),還需要進行解壓。

          然后,對響應資源做緩存。

          接下來,根據響應資源里的 MIME[3] 類型去解析響應內容(比如 HTML、Image各有不同的解析方式)。

          六、渲染頁面

          瀏覽器內核

          不同的瀏覽器內核,渲染過程也不完全相同,但大致流程都差不多。

          基本流程

          6.1. HTML 解析

          首先要知道瀏覽器解析是從上往下一行一行地解析的。

          解析的過程可以分為四個步驟:

          ① 解碼(encoding)

          傳輸回來的其實都是一些二進制字節數據,瀏覽器需要根據文件指定編碼(例如UTF-8)轉換成字符串,也就是HTML 代碼。

          ② 預解析(pre-parsing)

          預解析做的事情是提前加載資源,減少處理時間,它會識別一些會請求資源的屬性,比如img標簽的src屬性,并將這個請求加到請求隊列中。

          ③ 符號化(Tokenization)

          符號化是詞法分析的過程,將輸入解析成符號,HTML 符號包括,開始標簽、結束標簽、屬性名和屬性值。

          它通過一個狀態機去識別符號的狀態,比如遇到<,>狀態都會產生變化。

          ④ 構建樹(tree construction)

          注意:符號化和構建樹是并行操作的,也就是說只要解析到一個開始標簽,就會創建一個 DOM 節點。

          在上一步符號化中,解析器獲得這些標記,然后以合適的方法創建DOM對象并把這些符號插入到DOM對象中。


          <html><head> <title>Web page parsing</title></head><body> <div> <h1>Web page parsing</h1> <p>This is an example Web page.</p> </div></body></html>
          

          瀏覽器容錯進制

          你從來沒有在瀏覽器看過類似”語法無效”的錯誤,這是因為瀏覽器去糾正錯誤的語法,然后繼續工作。

          事件

          當整個解析的過程完成以后,瀏覽器會通過DOMContentLoaded事件來通知DOM解析完成。

          6.2. CSS 解析

          一旦瀏覽器下載了 CSS,CSS 解析器就會處理它遇到的任何 CSS,根據語法規范[4]解析出所有的 CSS 并進行標記化,然后我們得到一個規則表。

          CSS 匹配規則

          在匹配一個節點對應的 CSS 規則時,是按照從右到左的順序的,例如:div p { font-size :14px }會先尋找所有的p標簽然后判斷它的父元素是否為div。

          所以我們寫 CSS 時,盡量用 id 和 class,千萬不要過度層疊。

          6.3. 渲染樹

          其實這就是一個 DOM 樹和 CSS 規則樹合并的過程。

          注意:渲染樹會忽略那些不需要渲染的節點,比如設置了display:none的節點。

          計算

          通過計算讓任何尺寸值都減少到三個可能之一:auto、百分比、px,比如把rem轉化為px。

          級聯

          瀏覽器需要一種方法來確定哪些樣式才真正需要應用到對應元素,所以它使用一個叫做specificity的公式,這個公式會通過:

          1. 標簽名、class、id
          2. 是否內聯樣式
          3. !important

          然后得出一個權重值,取最高的那個。

          渲染阻塞

          當遇到一個script標簽時,DOM 構建會被暫停,直至腳本完成執行,然后繼續構建 DOM 樹。

          但如果 JS 依賴 CSS 樣式,而它還沒有被下載和構建時,瀏覽器就會延遲腳本執行,直至 CSS Rules 被構建。

          所有我們知道:

          • CSS 會阻塞 JS 執行
          • JS 會阻塞后面的 DOM 解析

          為了避免這種情況,應該以下原則:

          • CSS 資源排在 JavaScript 資源前面
          • JS 放在 HTML 最底部,也就是 </body>前

          另外,如果要改變阻塞模式,可以使用 defer 與 async,詳見:這篇文章[5]

          6.4. 布局與繪制

          確定渲染樹種所有節點的幾何屬性,比如:位置、大小等等,最后輸入一個盒子模型,它能精準地捕獲到每個元素在屏幕內的準確位置與大小。

          然后遍歷渲染樹,調用渲染器的 paint() 方法在屏幕上顯示其內容。

          6.5. 合并渲染層

          把以上繪制的所有圖片合并,最終輸出一張圖片。

          6.6. 回流與重繪

          回流(reflow)

          當瀏覽器發現某個部分發現變化影響了布局時,需要倒回去重新渲染,會從html標簽開始遞歸往下,重新計算位置和大小。

          reflow基本是無法避免的,因為當你滑動一下鼠標、resize 窗口,頁面就會產生變化。

          重繪(repaint)

          改變了某個元素的背景色、文字顏色等等不會影響周圍元素的位置變化時,就會發生重繪。

          每次重繪后,瀏覽器還需要合并渲染層并輸出到屏幕上。

          回流的成本要比重繪高很多,所以我們應該盡量避免產生回流。

          比如:

          • display:none 會觸發回流,而 visibility:hidden 只會觸發重繪。

          6.7. JavaScript 編譯執行

          大致流程

          可以分為三個階段:

          1. 詞法分析

          JS 腳本加載完畢后,會首先進入語法分析階段,它首先會分析代碼塊的語法是否正確,不正確則拋出“語法錯誤”,停止執行。

          幾個步驟:

          • 分詞,例如將var a=2,,分成var、a、=、2這樣的詞法單元。
          • 解析,將詞法單元轉換成抽象語法樹(AST)。
          • 代碼生成,將抽象語法樹轉換成機器指令。

          2. 預編譯

          JS 有三種運行環境:

          • 全局環境
          • 函數環境
          • eval

          每進入一個不同的運行環境都會創建一個對應的執行上下文,根據不同的上下文環境,形成一個函數調用棧,棧底永遠是全局執行上下文,棧頂則永遠是當前執行上下文。

          創建執行上下文

          創建執行上下文的過程中,主要做了以下三件事:

          • 創建變量對象
          • 參數、函數、變量
          • 建立作用域鏈
          • 確認當前執行環境是否能訪問變量
          • 確定 This 指向

          3. 執行

          JS 線程

          雖然 JS 是單線程的,但實際上參與工作的線程一共有四個:

          其中三個只是協助,只有 JS 引擎線程是真正執行的

          • JS 引擎線程:也叫 JS 內核,負責解析執行 JS 腳本程序的主線程,例如 V8 引擎
          • 事件觸發線程:屬于瀏覽器內核線程,主要用于控制事件,例如鼠標、鍵盤等,當事件被觸發時,就會把事件的處理函數推進事件隊列,等待 JS 引擎線程執行
          • 定時器觸發線程:主要控制setInterval和setTimeout,用來計時,計時完畢后,則把定時器的處理函數推進事件隊列中,等待 JS 引擎線程。
          • HTTP 異步請求線程:通過XMLHttpRequest連接后,通過瀏覽器新開的一個線程,監控readyState狀態變更時,如果設置了該狀態的回調函數,則將該狀態的處理函數推進事件隊列中,等待JS引擎線程執行。

          注:瀏覽器對同一域名的并發連接數是有限的,通常為 6 個。

          宏任務

          分為:

          • 同步任務:按照順序執行,只有前一個任務完成后,才能執行后一個任務
          • 異步任務:不直接執行,只有滿足觸發條件時,相關的線程將該異步任務推進任務隊列中,等待JS引擎主線程上的任務執行完畢時才開始執行,例如異步Ajax、DOM事件,setTimeout等。

          微任務

          微任務是ES6和Node環境下的,主要 API 有:Promise,process.nextTick。

          微任務的執行在宏任務的同步任務之后,在異步任務之前。

          代碼例子


          console.log('1'); // 宏任務 同步
          setTimeout(function() { console.log('2'); // 宏任務 異步})
          new Promise(function(resolve) { console.log('3'); // 宏任務 同步 resolve();}).then(function() { console.log('4') // 微任務})
          console.log('5') // 宏任務 同步
          

          以上代碼輸出順序為:1,3,5,4,2

          來源:4ark.me/post/b6c7c0a2.html,侵刪

          者 | MageByte團隊

          來源 | 碼哥字節(ID:MageByte)

          頭圖 | CSDN 下載自東方IC

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

          大致流程

          • URL 解析,解析 http 協議、端口、資源地址。

          • DNS 查詢:首先查詢本地 host,再訪問 DNS 服務器將 域名解析成 ip 地址。

          • 建立 TCP 連接。

          • 服務器收到請求后處理,并且構造響應返回給客戶端。

          • 客戶端接收 HTTP 報文響應。

          • 渲染頁面,最后有可能會四次揮手斷開連接,也可能不會而是復用連接。

          重點來了:

          • 如何理解 TCP 的三次握手與四次揮手?每次握手客戶端與服務端是怎樣的狀態?

          • 為何揮手會出現 2MSL,遇到大量 Socket 處在 TIME_WAIT 或者 CLOSE_WAIT 狀態是什么問題?

          • 三次握手與四次揮手的過程是怎樣的?

          • HTTP 的報文格式又是怎樣的?

          繼續閱讀本文,且聽碼哥字節答疑解惑,微信搜索 “碼哥字節”,關注公眾號更多硬核。

          URL 解析

          比如【碼哥字節】在思否發布的一篇文章的地址:https://segmentfault.com/a/1190000023475177。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四層模型

          1、應用層:發送 HTTP 請求

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

          • 請求行包含請求方法、URL、協議版本

          • 請求報頭(Request Header):由 “關鍵字: 值”對組成,每行一對,關鍵字與值使用英文 “:” 分割

          • 請求體:請求參數,并不是所有的請求有又請求參數。一般 get 參數 的格式 name=tom&password=1234&realName=tomson,也可以將參數放在 body 里面。

          2、傳輸層:TCP 傳輸報文

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

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

          可靠傳輸

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

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

          TCP擁塞控制

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

          流量控制

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

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

          3、網絡層:IP 協議查詢 MAC 地址

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

          4、鏈路層:以太網協議

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

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

          • 數據:數據包具體內容

          5、Mac 地址

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

          6、三次握手

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

          三次握手

          首先建立鏈接前需要 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 洪水攻擊。

          7、四次揮手

          我們只要關注 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 - 表示我方已關閉連接,正在等待服務端關閉??蛻舳税l了關閉連接的 FIN 報文后,服務器發回 ACK 應答,但是沒進行關閉,就會處于這種狀態。

          • TIME_WAIT - 雙方都正常關閉連接后,客戶端會維持 TIME_WAIT 一段時間,以確保最后一個 ACK 能成功發送到服務器端。停留時長為 2 倍的 MSL (報文最大生存時間),Linux 下大約是 60 秒。所以在一個頻繁建立短連接的服務器上通??梢钥吹匠汕先f的 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. 保證這次連接的重復數據段從網絡中消失,防止端口被重用時可能產生數據混淆;

          服務器處理請求并響應 HTTP 報文

          深入分析下 HTTP 報文到底是什么玩意。數據傳輸都是通過 TCP/IP 協議負責底層的傳輸工作, HTTP 協議基本不用操心,所謂的 “超文本傳輸協議” 似乎不怎么例會 “傳輸” 這個事情,那 HTTP 的核心又是什么呢?

          比圖 TCP 報文,它在實際要傳輸的數據之前附加了一個 20 字節的頭部數據,存儲 TCP 協議必須的額外信息,例如發送方的端口號、接收方的端口號、包序號、標志位等等。

          有了這個附加的 TCP 頭,數據包才能夠正確傳輸,到了目的地后把頭部去掉,就可以拿到真正的數據。這個很容易理解,設置起點與終點,不同協議貼上不同的頭部,到了對應目的地就拆下這個頭部,提取真正的數據。

          HTTP報文

          與 TCP/UDP 類似需要在傳輸數據前設置一些請求頭,不同的是 HTTP 是一個 “純文本” 的協議,所有的頭都是 ASCII 碼的文本,很容易看出來是什么。

          再者就是他的請求報文與響應報文的結構基本一樣,主要三大部分組成:

          1. 起始行(Start Line):描述請求或者響應的基本信息。

          2. Header:使用 key-value 的形式詳細說明報文信息。

          3. 空行。

          4. 消息正文(Entity):傳輸的數據,圖片、視頻、文本等都可以。

          這其中前兩部分起始行和頭部字段經常又合稱為“請求頭”或“響應頭”,消息正文又稱為“實體”,但與“header”對應,很多時候就直接稱為“body”。

          敲黑板了

          HTTP 協議規定報文必須包含 Header,而且之后必須有一個 “空行”,也就是“CRLF”,十六進制的“0D0A”,可以沒有 “body”。

          報文結構如下圖所示:

          HTTP報文

          截取一段報文:

          透視HTTP協議

          請求頭-起始行

          請求行由請求方法字段、URL 字段和 HTTP 協議版本字段 3 個字段組成,它們用空格分隔。例如,GET / HTTP/1.1。

          HTTP 協議的請求方法有 GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。

          GET 是請求方法, “/” 是請求的目標資源,“HTTP/1.1” 請求協議版本號。

          GET / HTTP/1.1 翻譯成文字大概就是:“hello,服務器,我要請求根目錄下的默認文件使用的是 HTTP 1.1 協議版本”。

          頭部 Header

          第二部分就是 Header,組成形式是 key:value,使用自定義頭需要注意事項:

          1. header 字段不區分大小寫,通常是首字母大寫;

          2. 字段名不允許有空格,可以使用 “-”,不能使用 “_”;

          3. 字段名必須緊接著 “:”,不能有空格,但是 “:” 后面可以有空格。

          4. 字段名順序沒有意義;

          瀏覽器接收響應并渲染數據

          接收到響應文本 HTML,則開始執行瀏覽器渲染機制。

          不同的瀏覽器渲染可能有所差異,但是基本按照以下步驟執行:

          1. 根據 HTML 解析 DOM 樹;

          2. 根據 CSS 解析出 CSS 規則樹;

          3. 結合 DOM 樹與 CSS 規則樹,生成渲染樹;

          4. 根據生成的渲染樹計算每個節點的信息;

          5. 根據節點信息繪制畫面展示給用戶。

          點分享

          1. 標簽:又稱元素,是HTML的基本組成單位雙標簽(絕大多數都是雙標簽):<標簽名>標簽體</標簽名>第一個標簽叫起始標簽,第二個標簽叫結束標簽例:<marquee>尚硅谷,讓天下沒有難學的技術!</marquee>單標簽:<標簽名/>/可以省略例:<input>
          2. 標簽名不區分大小寫,但推薦小寫,因為小寫更規范
          3. 標簽之間的關系:并列關系、嵌套關系,可以使用 tab 鍵進行縮進
          4. 1
            2
            3
            4
            5
            <marquee>
            尚硅谷,讓天下沒有難學的技術!
            <input>
            </marquee>
            <input>

          標簽屬性

          1. 用于給標簽提供附加信息
          2. 可以寫在起始標簽或單標簽中,形式如下:<標簽名 屬性名="屬性值" 屬性名="屬性值">
          3. 1
            2
            <marquee loop="1" bgcolor="orange">尚硅谷,讓天下沒有難學的技術!</marquee>
            <input type="password">
          4. 有些特殊的屬性,沒有屬性名,只有屬性值,如:<input disabled>

          不同的標簽,有不同的屬性;也有一些通用屬性(在任何標簽內都能寫)屬性名、屬性值不能亂寫,都是W3C規定好的屬性名、屬性值,都不區分大小寫,但推薦小寫雙引號,也可以寫成單引號,甚至不寫,但推薦寫雙引號標簽中不要出現同名屬性,否則后寫的會失效,例如:<input type="text" type="password">

          基本結構

          1. 想要呈現在網頁中的內容寫在body標簽中
          2. head標簽中的內容不會出現在網頁中
          3. head標簽中的title標簽可以指定網頁的標題
          4. 1
            2
            3
            4
            5
            6
            7
            8
            <html>
            <head>
            <title>網頁標題</title>
            </head>
            <body>
            ......
            </body>
            </html>

          注釋

          1. 特點:注釋的內容會被瀏覽器所忽略,不會呈現到頁面中,但源代碼中依然可見
          2. 作用:對代碼進行解釋和說明
          3. 寫法
          4. 1
            2
            3
            4
            <!-- 下面的文字只能滾動一次 -->
            <marquee loop="1">尚硅谷</marquee>
            <!-- 下面的文字可以無限滾動 -->
            <marquee>尚硅谷123</marquee>
          5. 注釋不可以嵌套

          文檔聲明

          1. 作用:告訴瀏覽器當前網頁的版本
          2. 寫法
            1. 舊寫法:要依網頁所用的HTML版本而定,寫法有很多參考:W3C QA - 可在 Web 文檔中使用的 Doctype 聲明的推薦列表
            2. 新寫法:W3C 推薦使用 HTML 5 的寫法
            3. 1
              2
              3
              4
              5
              <!DOCTYPE html>

              <!DOCTYPE HTML>

              <!doctype html>
          3. 文檔聲明必須在網頁的第一行,且在html標簽的外側

          字符編碼

          1. 計算機對數據的操作存儲時,對數據進行:編碼讀取時,對數據進行:解碼
          2. 編碼、解碼,會遵循一定的規范 —— 字符集
          3. 常見的字符集ASCII:大寫字母、小寫字母、數字、一些符號,共計128個ISO 8859-1:在 ASCII 基礎上,擴充了一些希臘字符等,共計是256個GB2312:繼續擴充,收錄了 6763 個常用漢字、682個字符GBK:收錄了的漢字和符號達到 20000+ ,支持繁體中文UTF-8 :包含世界上所有文字與符號
          4. 為了讓瀏覽器在渲染html文件時,不犯錯誤,可以通過meta標簽配合charset屬性指定字符編碼
          5. 1
            2
            3
            <head>
            <meta charset="UTF-8"/>
            </head>

          設置語言

          1. 主要作用讓瀏覽器顯示對應的翻譯提示有利于搜索引擎優化
          2. 具體寫法:<html lang="zh-CN">
          3. lang屬性的編寫規則語言-國家/地區zh-CN :中文-中國大陸(簡體中文)zh-TW :中文-中國臺灣(繁體中文)zh :中文en-US :英語-美國en-GB :英語-英國語言—具體種類(已不推薦使用)zh-Hans :中文—簡體zh-Hant :中文—繁體W3School 上的說明:《語言代碼參考手冊》 、《國家/地區代碼參考手冊》 W3C官網上的說明:《Language tags in HTML》

          標準結構

          1. HTML標準結構如下
          2. 1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            <!DOCTYPE html>
            <html lang="zh-CN">

            <head>
            <meta charset="UTF-8">
            <title>Document</title>
            </head>

            <body>

            </body>

            </html>

          VSCode 刪除行快捷鍵:Ctrl+Shift+K

          1. 輸入!,隨后回車即可快速生成標準結構
          2. 配置VScode 的內置插件 emmet ,可以對生成結構的屬性進行定制
          3. 在存放代碼的文件夾中,存放一個 favicon.ico 圖片,可配置網站圖標

          主站蜘蛛池模板: 国产人妖视频一区二区| 一区二区高清在线| 一区二区三区内射美女毛片| 不卡一区二区在线| 精品国产一区二区三区无码| 麻豆果冻传媒2021精品传媒一区下载 | 日本一区二区三区四区视频| 一本一道波多野结衣AV一区| 久久久精品人妻一区二区三区四| 亚洲毛片不卡av在线播放一区| 濑亚美莉在线视频一区| 亚洲日本久久一区二区va| 亚洲国产一区二区三区青草影视| 精品乱子伦一区二区三区高清免费播放| 色天使亚洲综合一区二区| 国产精品视频一区麻豆| 亚洲欧洲日韩国产一区二区三区| 男女久久久国产一区二区三区| 一区二区精品在线| 亚洲一区中文字幕在线电影网 | 99久久精品国产免看国产一区| 高清一区高清二区视频| 色婷婷香蕉在线一区二区| 精品无人区一区二区三区在线 | 国产激情一区二区三区在线观看| 97人妻无码一区二区精品免费| 精品人妻AV一区二区三区| 国产香蕉一区二区在线网站| 亚洲一区在线视频观看| 亚洲愉拍一区二区三区| 色一情一乱一伦一区二区三区日本| 韩国女主播一区二区| 日本一区二区三区不卡视频中文字幕| 国产一区二区三区无码免费 | 精品一区二区三区水蜜桃| 国产av夜夜欢一区二区三区| 一区免费在线观看| 国产一区二区三区在线影院 | 午夜影院一区二区| 日本精品一区二区三区视频| 日韩精品无码Av一区二区|