0. 全書概覽
本書以使用者在瀏覽器進行一次進行 HTTP 訪問作為線索,講述網路的運作機制。在使用者在瀏覽器輸入網址開始,到瀏覽器接顯示出頁面為止整的個過程中,全書按照控制權轉移的順序,依次介紹了網路的兩個主要的組成部分:資訊 傳輸機制(網路協議和路由器、交換機等) + 應用軟體(瀏覽器、Web伺服器),在整個網路請求之中,是如何分工和協作的。
1. 第一章
第一章中,主要介紹瀏覽器從接收到使用者輸入的 URL 開始,到開始傳送 HTTP 請求訊息這一過程。
- 解析 URL
- 生成 HTTP 報文
- 確定 Web 伺服器 IP 地址
- 委託 OS 傳送報文
1.1 解析 URL
URL 是什麼
URL(Uniform Resource Locator)統一資源定位符,用於描述某一資源的位置,輸入 URL 也就類似於,打電話時要先輸入對方的電話號碼,URL 標識了這次請求的協議型別和目的地。
URL 的幾種型別
URL 開頭到第一個 ":" 之前的部分,標識了 URL 的協議型別,如http、ftp、file 等。對於不同的網路協議,URL 的寫法也有各自的規則,本書將重點介紹的是 HTTP 網路協議。
1.2 生成 HTTP 報文
經過解析 URL,我們已經知道了我們要訪問的目標。接下來的一步,就是生成傳送給訪問目標的請求報文,請求報文的格式是有嚴格規定的。那麼,我們再來看看 HTTP 報文的格式。
1.2.1 HTTP 請求報文的格式
- 請求行
請求報文的首行,由 Method + URI + HTTP-Version 共同組成,它們之間使用空格隔開。
關於 method,method 用於標識請求的動作型別,如 新增、刪除、讀取,它的值並不在 URL 中體現,而是由瀏覽器根據實際情況來判定。 - 訊息頭
訊息頭與請求行之間沒有空行,它由若干鍵值對組成,每個鍵值對佔一行。訊息頭的最後,有一個空行,標識訊息頭結束,並以此來隔開訊息頭與訊息體。
欄位名 : 欄位值
··· ··· : ··· ··· - 訊息體
訊息體用於承載此次請求想要提交的資訊,往往在 PUT、POST 請求才會用到
1.2.2 HTTP 響應報文的格式
- 響應行
響應報文的第一行,由 HTTP-Version + 狀態碼 + 狀態短語 共同組成。響應報文的格式中,除了這第一行響應行的格式區別與請求行,其餘部分的格式,都與請求報文一致。 - 訊息頭
格式同請求報文 - 訊息體
格式同請求報文
1.3 獲取 Web 伺服器的 IP 地址
生成了請求報文之後,那麼接下來就應該委託 協議棧向 Web 伺服器傳送報文了。但是,在傳送報文之前,還存在一個問題,就是通過解析 URL,只拿到了目標資源的 Domain,而委託協議棧發報文,必須要提供的不是 Web 伺服器的 Domain,而是 Web 伺服器的 IP 地址。那麼,什麼是 IP,又怎樣才能將 Domain 轉化為 IP 呢?
1.3.1 IP 地址的基本知識
- IP 地址的格式:是一串 32 bit 的數字,8 bit(1 byte) 一組分為 4 組,每組之間用 " . " 隔開。
- IP 的內部構造:地址中包含『網路號』+『主機號』,但是,他們二者在 32 bit 中所佔的位數,並不固定,而是在元件網路時由使用者自定義的。因此,除了 IP 地址之外,還需要一個附加資訊(子網掩碼),來標識 IP 地址的內部構造。
- 子網掩碼,與 IP 地址的長度相同,也是一串 32 bit 的數字。其中,左邊一半都是 ‘1’,右邊一半都是 ‘0’. 其中‘1’的部分代表網路號,‘0’的部分代表『主機號』
1.3.2 從 Domain 到 IP 地址:DNS
瞭解完什麼是 IP 地址,接下來,再來說說怎樣根據 Domain 來獲取 IP 地址。此時,輪到 DNS (Domain Name System)閃亮登場了,DNS 是一種維護 Domain 和 IP 地址之間對映關係的網路伺服器。因為在 Socket 庫中,封裝了查詢 IP 地址的功能。所以,在建立 Socket 時,只要傳入 Domain 就可以了,Socket 內部會執行對 DNS 的詢問。
為啥既要有 Domain ,又要用 IP 地址呢 ?Domain 是為了方便人記憶,而簡短的 IP 地址,則能夠減輕路由器路由的負擔。
DNS 的 IP 地址從哪來呢 ?它是作為 TCP/IP 的是個設定專案,在 OS 中提前設定好的,不需要去查詢。
1.3.3 全球 DNS 大接力
由於全球的域名數量,不止是成百上千,將所有的 Domain-IP地址 對映關係全部維護在同一臺 DNS 伺服器,是不可能做到的。因此,需要很多的 DNS 伺服器分散式的儲存 Domain-IP地址 的對映資訊,那麼,這些遍佈全球的 DNS 伺服器之間,是如何協作的呢?
- 域名的層級關係
在介紹 DNS 伺服器之間的協作方式之前,先要介紹一下 Domain 的層級關係。域名是由 ‘ . ’ 分割的一個字串。它的層級,也同樣由 ‘ . ’ 來進行劃分,越靠右側的位置,層級越高。如 ‘https://dubbo.apache.org/’ 域名中,層級最高的是 ‘org’,其次是 ‘apache’,再次是 ‘dubbo’。 定位 DNS 伺服器並取得 IP 地址
既然 Domain 是分層級的,那麼 DNS 伺服器當然也會按照層級來進行儲存。- 首先,全球共有 12 個根域名伺服器,它們會儲存一級域名的 DNS 服務 IP 地址;
- 其次,維護一級域名的 DNS 伺服器之中,又會儲存它維護了自己域內的二級域名的對映關係的 DNS 伺服器的 IP 地址;
- 同理,三級 DNS 伺服器,又維護了四級 DNS 伺服器的 IP 地址,如此層層向下遞進,直到拿到 跟完整 Domian 相匹配的 IP 地址,然後返回給發起請求的 DNS 客戶端。
- 另外,每臺 DNS 伺服器,都要維護 Root DNS 伺服器的 IP 地址,如此一來,只要找到任何一臺 DNS 伺服器,就可以獲取任意的一個域名對應的 IP 地址了。(Root DNS 伺服器全球共有 12 個)
1.4 委託協議棧傳送訊息
從 DNS 那裡取得了 Web 伺服器的 IP 地址之後,滿足了協議棧資料的要求,所以,下一步,瀏覽器將會委託協議棧向 Web 伺服器傳送報文了。
首先,協議棧將瀏覽器與 Web 伺服器之間相互傳送訊息的動作,抽象成為了『管道與插孔』的模型。通訊時,在瀏覽器端、Web 伺服器端,各有一個『插孔』,兩個『插孔』由一根『管道』相連線,管道是雙向的,雙方都可以向管道讀寫資料。
- 服務端建立起 Socket『插孔』,等待被連線
- 瀏覽器建立 Socket,瀏覽器呼叫協議棧程式,建立一個 Socket ,並隨機分配埠,由於瀏覽器程式同時可能會與多個 Web 伺服器進行通訊,因此,協議棧會返回一個描述符,用來標識這個新建立的 Socket。
- 瀏覽器發起連線,將兩個 Socket 用一根管子連線起來(需要埠號),此時,瀏覽器需要告知協議棧三個引數,Socket 的描述符、Web 伺服器的 IP 地址、Web 伺服器的埠號。建立連線的同時,瀏覽器會將自己Socket 所使用的 IP 地址、埠號資訊告知 Web 伺服器,以便 Web 伺服器向自己的 Socket 傳送響應報文。
- 收發訊息,兩邊的程式,分別向自己的 Socket 寫入資料,並監聽直到獲取由 Web 伺服器向自己的 Socket 所傳送的相應報文。
- Web 伺服器傳送完響應報文,直接關閉 Socket ,或者等待瀏覽器關閉 Socket 後再關閉自己的 Socket。
這個小節中,從巨集觀上描述了 瀏覽器 與 Web 伺服器雙方進行通訊的機制,其中的具體細節,將在下一章中詳細進行描述。