【多圖長文預警,建議先碼】在瀏覽器地址欄輸入 URL 到頁面渲染之間都經歷了什麼?這是一道很經典的問題,能夠很全面的考驗面試者對於網絡知識的理解。這之間的過程是一環套一環,下面筆者經過這題來科普一下基礎的網絡知識。php
當咱們在瀏覽器地址欄輸入信息時,瀏覽器就已經開始進行工做了。首先它會監聽咱們輸入的信息並嘗試匹配出你想要訪問的網址或關鍵詞,以 chrome
爲例,它會猜咱們想要什麼,給出下面的建議項:css
咱們在地址欄輸入知乎首頁的連接 zhihu.com
後敲下回車,命令瀏覽器搜索信息。接着大體會對輸入的信息進行如下判斷:html
URL
連接。URL
。好比輸入 zhihu.com
則可能會在前面添加 www
。瀏覽器根據咱們輸入的信息判斷出 zhihu.com
是一個合法 URL
,並被補全爲 www.zhihu.com
。前端
本章參考資料:ios
常常上網的朋友常常能據說 URL
這個名詞,那麼它具體是幹嗎用的呢?git
URL
全稱爲統一資源定位系統(uniform resource locator),用於表示一個因特網(Internet)上標準的資源的地址。就像每戶人家都會有個門牌地址同樣。維基百科對 URL
的術語上是這樣解釋:github
每一個 HTTP URL
都符合通用 URI
的語法(關於 URL
與 URI
的差異參請看下文的列參考資料)。URI
通常語法由五個的分層序列的組分:web
URI = scheme:[//authority]path[?query][#fragment] URI = 方案:[//受權]路徑[?查詢][#片斷ID]
權限組件 (authority) 又分爲三個子組件:面試
authority = [userinfo@]host[:port]
它在語法圖表示爲:算法
從術語上看好像有點抽象?沒有關係,咱們經過瀏覽器內部提供的 location
的接口來輔助理解,該接口表示其連接到的對象的位置(URL)。
咱們另開一個標籤頁,隨便打開一個較爲複雜的 URL,如:
https://github.com/anran758/Front-End-Lab/tree/master/css?name=anran758&uid=234098&shareId=456#layout
接着在控制檯的 Console
面板中直接輸入 location
並敲下回車,它會輸出一個對象,該對象內包含當前頁面上的 URL 信息。
{ "href": "https://github.com/anran758/Front-End-Lab/tree/master/css?name=anran758&uid=234098&shareId=456#layout", "ancestorOrigins": {}, "origin": "https://github.com", "protocol": "https:", "host": "github.com", "hostname": "github.com", "port": "", "pathname": "/anran758/Front-End-Lab/tree/master/css", "search": "?name=anran758&uid=234098&shareId=456", "hash": "#layout" }
咱們拿這個對象與 URL 的屬於一一對應,就能夠清晰看出他們之間的對應關係:
URL 術語 | location 對象的 key | 匹配項 |
---|---|---|
scheme | protocol | https |
host | hostname | github.com |
path | pathname | /anran758/Front-End-Lab/tree/master/css |
query | search | ?name=anran758&uid=234098&shareId=456 |
fragment | hash | #layout |
scheme
(方案),多時候狀況下也稱爲 protocol
(協議),尾部跟隨一個 :
做爲分隔host
(主機名), 它能夠是一個 IP 或是一個域名(下文會講解二者的概念)path
(路徑),以 /
區別每一層目錄結構的名稱。query
(查詢),以 ?
爲起點,以 &
分隔鍵值。 name
就是鍵,anran758
就是值。在頁面上,前端能夠經過 URL
來傳遞參數;在接口上,後端能夠根據 GET
請求取得對應查詢條件fragment
(片斷),以 #
爲起點的部分。咱們一般稱這部分爲哈希,它在瀏覽器上有特殊的做用。 id=layout
的元素,那麼頁面就會滾動到該元素之上。就像咱們打開上面給出的示例 URL
後,頁面加載後自動滾動在標題爲 layout
上。以上是咱們在地址欄中常見的 URL(URI)
格式,但不夠全面。比方說咱們帶上端口後,直接訪問 https://github.com:443
會發現地址欄上並無顯示出端口號,這是爲何呢?
這是由於若是咱們訪問的 URL
使用的是以 https
開頭的協議,那麼 HTTPS
協議的默認的端口就是 443
。即使咱們特地補全這個端口號,瀏覽器仍是默認會將該端口隱去。
同理,咱們訪問的是 http
協議,他的默認端口是 80
端口,也會自動隱藏掉。只有當咱們訪問與該協議默認端口不一致時,瀏覽器纔會顯示出來。好比 http://localhost:8000/analysis/project
就能看到它能在地址欄上正確的顯示出來(筆者這裏是以 chrome
瀏覽器爲例,不一樣瀏覽器可能有不一樣的行爲)。
完整的 URL
例子能夠參見維基百科給出的示例:
userinfo host port ┌──┴───┐ ┌──────┴──────┐ ┌┴┐ https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top └─┬─┘ └───────────┬──────────────┘└───────┬───────┘ └───────────┬─────────────┘ └┬┘ scheme authority path query fragment ldap://[2001:db8::7]/c=GB?objectClass?one └┬─┘ └─────┬─────┘└─┬─┘ └──────┬──────┘ scheme authority path query mailto:John.Doe@example.com └─┬──┘ └────┬─────────────┘ scheme path news:comp.infosystems.www.servers.unix └┬─┘ └─────────────┬─────────────────┘ scheme path tel:+1-816-555-1212 └┬┘ └──────┬──────┘ scheme path telnet://192.0.2.16:80/ └─┬──┘ └─────┬─────┘│ scheme authority path urn:oasis:names:specification:docbook:dtd:xml:4.1.2 └┬┘ └──────────────────────┬──────────────────────┘ scheme path
接着瀏覽器分析 URL 信息後,會從 URL 取出方案(協議類型)。這個方案能夠是常見的 http:
,也能夠像 chrome 內置協議 chrome:
。再根據不一樣的協議進行不一樣的解析。
咱們在地址欄上輸入的是 zhihu.com
,沒有指定要使用哪一個協議,那這個這個判斷的權利交給了瀏覽器,瀏覽器經過內置的方案來決定對 URL
信息進行補全。好比 chrome
可能會對該連接補全爲 https://www.zhihu.com
。
接着瀏覽器從 URL
中提取出主機名(host
)信息。它多是一個 IP 地址,也能夠多是一個域名地址。
host port ┌──────┴────┐ ┌┴┐ https://www.zhihu.com:443/ └─┬─┘ └────────┬────────┘ scheme authority host port ┌─────┴─────┐ ┌┴─┐ http://192.168.6.106:8000/ └─┬─┘ └────────┬────────┘ scheme authority
下面來了解一下關於 IP 地址
和域名
這兩個概念。
本章參考資料:
因特網(Internet)就像個學校,每一個資源都有本身的座位。當你獲取某個資源時,首先須要肯定資源的所在地,就像你要去別人家取貨那起碼得知道人家的地址。
IP 地址(Internet Protocol Address) 就是用於標識網絡上設備的數據標籤,也能夠通俗的理解爲住宅門牌號。它主要有 IPv4
、IPv6
兩個版本。
IPv4
使用 32 位地址, 地址空間爲 4,294,967,296(2^32)
。它有 3 種常見的標記法,即:二進制標記法、點分十進制標記法、十六進制標記法,其中最常採用的標記法是方便人們記憶的點分十進制。如下是三者之間的比較:
IPv4 標記法 | 表示方式 |
---|---|
二進制 | 11000000 10101000 00000001 00000001 |
點分十進制 | 192.168.1.1 |
十六進制 | 0xC0A80101 |
IPv4
早已在咱們身邊普及。比方說咱們須要重設 WIFI 密碼,那得要登陸路由器廠商提供的路由器管理後臺(Admin),這個管理後臺的登陸地址一般是廠商默認設置的本地 IP 地址,如 192.168.1.1
。
在 IPv4 的原始設計中,IP 地址分爲兩部分,分別是 8 位網絡地址和 24 位主機位。由於局域網早期出現時,只有一些又大又少的網絡。這種結構最多容許有 256 個網絡,很快就發現這種結構徹底不夠用。
爲了克服這個限制,1981 年的 RFC 791 對 IP 地址定義進行了修改,定義了分類地址結構。修訂後系統定義了五個類,分別是 A、B、C、D、E 五類。如下是分類地址結構的 IPv4 地址空間劃分表:
類 | 地址範圍 | 高序位 | 用途 | 百分比 | 網絡地址位數 | 主機位數 | 網絡數 | 每一個網絡的主機數 |
---|---|---|---|---|---|---|---|---|
A | 0.0.0.0 ~ 127.255.255.255 | 0 | 單播/特殊 | 1/2(128/256) | 8 | 24 | 128 | 16,777,216 |
B | 128.0.0.0 ~ 191.255.255.255 | 10 | 單播/特殊 | 1/4 | 16 | 16 | 16384 | 65,536 |
C | 192.0.0.0 ~ 223.255.255.255 | 110 | 單播/特殊 | 1/8 | 24 | 8 | 2,097,152 | 256 |
D | 224.0.0.0 ~ 239.255.255.255 | 1110 | 組播 | 1/16 | N/A | N/A | N/A | N/A |
E | 240.0.0.0 ~ 255.255.255.255 | 11110 | 保留 | 1/16 | N/A | N/A | N/A | N/A |
咱們從表中能夠得知,A、B、C 類用於爲因特網(單播地址)中的接口分配地址,還有一些在特殊狀況下使用不被分配的 IP。
單播和組播的概念很好理解。單播是指客戶端與服務器之間的點到點鏈接。就像你跟小姐姐聊天是一對一之間的交流。
組播則是指在發送和接收者實現點對多點鏈接。下面二狗子的表情包很精準的闡述出組播的概念:
二狗子忽然站起來對圈子(組播組)裏的其餘朋友說:"你們聽我說,我發現咱們都是狗!!"。二狗子發出了一條消息,組播組內的其餘狗子同時接收到了這條消息。
使用分類地址劃分後,不一樣類地址能夠擁有不一樣規模的網絡數和主機數。好比,A 類地址僅能分配 128 個網絡給不一樣站點用,但一個網絡內分配給 16,777,216(2^24)
臺主機使用。而 C 類地址雖然能分配 2,097,152(2^21)
個網絡,但每一個網絡只能容納 256 臺主機。這樣就能夠預先估計規模大小,而後再申請分類分配網絡號,解決了早期不夠用的問題。
隨着互聯網發展,分類網絡的形式使得不少地址空間沒有被合理的利用上,C 類地址不足以承載太大的網站,進而去申請 B 類地址。致使 B 類地址迅速減小。IP 地址不夠用的狀況又出現了。爲了解決這些狀況,RFC 在基於 IPv4 地址上提出瞭如下的方案:
1985 年,隨着 RFC 950 的發佈,開始將現有的分類網絡劃分爲子網。隨後在 1987 年發佈的 RFC 1109 中引入可變長度子網掩碼(VLSM),該劃分變得更加靈活。1993 年,基於可變長度子網掩碼 RFC 1517 引入了無類域間路由(CIDR), 正式地取代了分類網絡,分類網絡也所以被稱爲「有類別」的。
CIDR 被設計爲能夠從新劃分地址空間,所以小的或大的地址塊都可以分配給用戶。CIDR 建立的分層架構由互聯網號碼分配局(IANA)和區域互聯網註冊管理機構(RIR)進行管理,每一個 RIR 均維護着一個公共的 WHOIS 數據庫,以此提供 IP 地址分配的詳情。
-- 以上 IPv4 地址方案發展歷史截取至維基百科
雖然經過以上幾種 IPv4 地址分配方案緩解地址耗盡的問題,但仍是治標不治本。爲了完全解決 IPv4
地址耗盡的問題,1998 年對使用 128 位 IP 地址的 IP(IPv6)新版本進行了標準化。
IPv6
地址的出現不只解決了 IPv4 地址空間不夠的問題,還實現了 IPv4 中不存在的功能。
在 IPv6 中,地址大小從 IPv4 中的 32 位增長到 128 位,從而提供了多達 2128 個(大約 3.403 × 10^38
)地址。這個數字什麼概念呢?咱們以維基百科統計的世界人口來對比。截止至 2019.05,世界人口約爲 77 億人(7.7 × 10^9)。所以在可預見的將來裏,這被認爲是夠用了的。
IPv6
地址爲 128 位元長,但一般寫做 8 組,每組 4 個十六進制數的形式。若是四個數字都是 0,能夠被省略。例如:
2001:0db8:85a3:0000:1319:8a2e:0370:7344 # 上面的 IPv6 等價於下面這條。注意雙冒號 2001:0db8:85a3::1319:8a2e:0370:7344
爲避免 IPv6
地址的冒號與方案的冒號衝突,在 IPv6
地址在 URL 上是經過中括號包裹,以百度的 IPv6 地址爲例:
http://[2400:da00:2::29]/ # 等價於 http://ipv6.baidu.com/
目前咱們見到更多的是 IPv4
地址。IPv6 是將來的主流,目前仍然在部署中。國內的部署狀況能夠在百度百科《IPv6》的發展歷史中能找到相關的描述:
2018 年 6 月,三大運營商聯合阿里雲宣佈,將全面對外提供 IPv6 服務,並計劃在 2025 年前助推中國互聯網真正實現「IPv6 Only」 。
7 月,百度雲制定了中國的 IPv6 改造方案。
8 月 3 日,工信部通訊司在北京召開 IPv6 規模部署及專項督查工做全國電視電話會議,中國將分階段有序推動規模建設 IPv6 網絡,實現下一代互聯網在經濟社會各領域深度融合。
11 月,國家下一代互聯網產業技術創新戰略聯盟在北京發佈了中國首份 IPv6 業務用戶體驗監測報告顯示,移動寬帶 IPv6 普及率爲 6.16%,IPv6 覆蓋用戶數爲 7017 萬戶,IPv6 活躍用戶數僅有 718 萬戶,與國家規劃部署的目標還有較大距離。2019 年 4 月 16 日,工業和信息化部發布《關於開展 2019 年 IPv6 網絡就緒專項行動的通知》。5 月,中國工信部稱計劃於 2019 年底,完成 13 個互聯網骨幹直聯點 IPv6 的改造。
好啦,關於 IP 地址的基礎概念就講到這裏。關於 IP 地址更深刻的知識能夠去找相關的專業教材或書籍,本文將不過多贅述。
本章參考資料:
理論上咱們直接使用 IP 地址就能夠訪問資源了。但直接經過 IP 地址來訪問會存在一個問題,那就是 IP 地址不便於人類記憶。考慮如下場景對話:
"嘿朋友。最近我作了個主頁,有空來我留言板踩踩唄?","沒問題呀,那麼地址是什麼呢?"。(如下彈出一個選項框)
選項A: http://[2400:da00:2::29]/ 選項B: http://183.232.231.174/ 選項C: http://www.baidu.com/
將上面三個選項進行對比就能發現:若是咱們十分硬核的選擇了 A、B 兩項,那你的朋友可能會給你翻個白眼。這樣的地址誰想記呀!!即使是朋友願意記下你的 IP 地址,但把該網站的定位轉爲商業網站後,顯然這就有點爲難用戶了。
tips: 在命令行使用
nslookup baidu.com
能夠得到百度的 ip 地址
所以,爲了克服 IP 地址不便於人類記憶和理解的狀況,人們設計出域名來輔助記憶。
域名(Domain) 在術語上定義,是由一串用點分隔的字符組成的互聯網上某一臺計算機或計算機組的名稱,用於在數據傳輸時標識計算機的電子方位。它有必定的天然語言含義。因此它至關因而 IP 地址的一個映射。
你不是 IP 地址記不住嗎?那我把 IP 地址映射爲人們熟知的拼音語句、英語單詞等常見詞語。183.232.231.174
我能夠映射爲 taobao.com
、 baidu.com
、12306.cn
。這樣是否是好記多了?
確實,IP 地址被映射爲域名後,人們記域名方便方便多了。但問題又來了,底層計算機並不認識域名這種東西、它尋址仍是得經過 IP 地址來尋址。發起請求時須要有應用告訴計算機這個域名的 IP 地址是什麼。
域名系統(Domain Name System, 下文統一簡稱爲 DNS) 的任務就是負責將域名解析爲 IP 地址。這個解析的過程也被稱爲 名稱解析(name resulution)。
DNS
是互聯網上重要的基礎應用程序,它做爲一個分佈式數據庫,域名服務器分佈在世界各地,儲存着域名與 IP 地址的映射關係,每一個域名服務器上值存儲了部分域名信息。所以爲了完成域名解析,經過須要在多個域名服務器之間進行查詢。
DNS
爲了實現域名的有效管理與高效的查詢,它是按層級結構進行組織的,而且該層次結構與域名的結構( .
分隔)相對應,每一個以點分隔的爲 標籤(label
)。它所使用的全部名稱集合構成了 DNS 名稱空間(name space)。
當前的名稱空間是一棵域名樹結構,位於頂部的樹根(root
, 一般爲咱們稱之爲根域名服務器)爲命名。樹第一層爲頂級域名(Top level Domian, TDL),TDL 再往下就是子域名。域名的層級是從右往左看:
三級域名.二級域名.頂級域名.根域名 三級域名 頂級域名 ┌┴┐ ┌┴┐ www.zhihu.com └─┬─┘ 二級域名
所以 www.zhihu.com
完整的域名應該是 www.zhihu.com.
。後面的 .
至關於 .root
,因爲每一個域名的根節點都是 root
,所以 .root
就被省略爲 .
。咱們直接訪問 zhihu.com.
是能正確的打開知乎首頁的。
一個服務器所管轄的範圍叫作區(zone)。每個區設置相應的權威域名服務器,用於保存該區中全部的主域名到 IP 地址的映射。其中 DNS 服務器的管轄範圍不是以 「域」 爲單位,而是以 「區」 爲單位。域名服務器根據其主要保存的域名信息以及在域名解析過程當中的做用等,能夠分爲根域名服務器、頂級域名服務器、權威域名服務器。
根域名服務器是最重要的域名服務器,由於全部域名解析操做均離不開它們。在因特網上指定了 13 個邏輯根名稱服務器,邏輯名稱的格式爲字母 .root-servers.net
,字母範圍從 a 到 m。如: a.root-servers.net
、d.root-servers.net
等。
頂級域名服務器負責管理在該頂級域名服務器註冊的全部二級域名。頂級域名服務器的名稱對應着域名的最後一個名稱。如 www.zhihu.com
的頂級域名服務器名稱是 com
。
權威域名服務器,負責一個區的域名服務器,保存該區中的全部主機的域名到 IP 地址的映射。任何一個擁有域名的主機,其域名與 IP 地址的映射關係等信息都存儲在所在網絡的權威域名服務器上。在進行域名解析時,只要找到被查詢域名主機註冊的權威域名服務器,就能夠得到該域名對應的 IP 地址信息。
任何一臺主機(PC、手機等)在網絡地址配置時,都會配置一個 DNS 服務器做爲默認域名服務器,這樣這臺主機在任什麼時候候須要進行域名解析,都會將域名查詢發送給該服務器,這個默認服務器咱們稱之爲本地域名服務器。在 MacOS 環境下能夠輸入如下命令來查看 DNS 的配置:
➜ blog git:(master) ✗ scutil --dns DNS configuration resolver #1 nameserver[0] : 172.20.10.1 if_index : 5 (en0) flags : Request A records reach : 0x00020002 (Reachable,Directly Reachable Address) resolver #2 domain : local options : mdns timeout : 5 flags : Request A records reach : 0x00000000 (Not Reachable) order : 300000 resolver #3 domain : 254.169.in-addr.arpa options : mdns timeout : 5 flags : Request A records reach : 0x00000000 (Not Reachable) order : 300200 resolver #4 domain : 8.e.f.ip6.arpa options : mdns timeout : 5 flags : Request A records reach : 0x00000000 (Not Reachable) order : 300400 # 省略其餘配置信息.. DNS configuration (for scoped queries) resolver #1 nameserver[0] : 172.20.10.1 if_index : 5 (en0) flags : Scoped, Request A records reach : 0x00020002 (Reachable,Directly Reachable Address)
從緩存的角度來看,有分 DNS 服務器緩存和應用級 DNS 緩存。
瀏覽器向 DNS 服務器發起請求,DNS 會從本身的緩存中讀取記錄,如沒有結果才向上一層請求,這是屬於應用級緩存。chrome
早期能夠經過訪問 chrome://net-internals/#dns
來查看瀏覽器緩存的 DNS 記錄,但不知什麼緣由如今把查看 DNS 信息的頁面給砍掉了,只留清除 DNS 緩存的功能。而 Firefox
能夠直接訪問 about:networking#dns
查看對應的域名映射。
除了 DNS 服務器與 DNS 緩存外,其實還有一種途徑能讀取域名映射,那就是 hosts
文件。
hosts
文件是純文本文件。從歷史的角度看,hosts
文件出現的比 DNS 服務器還早。最初在 Internet 的前身 ARPANET 中,其成員 SRI International 手動維護並分享的一個名爲 HOSTS.TXT 的文件。它負責將主機名稱映射到相應的 IP 地址。
因爲我的網絡不斷龐大以後,對 hosts 文件進行管理的難度也愈來愈大,因而在 1983 年 DNS 系統開始開發,1984 年獲得了發展。而且隨着網絡的發展,DNS 能夠自動提供動態的主機名解析,所以 hosts
成爲了一個能夠做爲備用手段的名稱解析機制。
與 DNS 不一樣的是,hosts 文件是能夠由用戶改寫的,是屬於操做系統級別的 IP 地址映射。同時在一些操做系統上,hosts 文件可能會比其餘域名解析器(如 DNS 服務器)會具備更高的優先級。
hosts 文件在不一樣操做系統下路徑是不同的。如下給出常見的操做系統路徑:
# win7 +, %SystemRoot%\ 系統根路徑默認爲 c 盤,也就是 c:\ %SystemRoot%\System32\drivers\etc\hosts # Unix、類Unix系統(例如 Linux、MacOs 等) /etc/hosts
hosts 文件內容由第一行文本字段中的 IP 地址和一個或多個主機名組成的文本行。每一個字段都用空格隔開(出於歷史緣由,一般首選使用 Linux 上的 hosts 直接複製到 window 上可能不會生效)。井號(#) 後文字爲註釋信息,文件中的徹底空白行將被忽略。典型的主機文件可能包含如下內容:
127.0.0.1 localhost ::1 localhost
除此以外,hosts 文件還能夠作其餘用途。
好比本來咱們開發環境的 URL 多是 192.168.6.106:8000
, 如今頁面上有一個強依賴於當前 URL 域名的功能或校驗。但咱們得要完成測試開發,這怎麼辦呢?總不能先部署上線再測試吧,這多麻煩呀..
這裏就能夠經過修改本地的 hosts 文件,將 192.168.6.106
映射 www.example.com
,而後咱們直接訪問 www.example.com:8000
進行測試便可。
再好比,咱們瀏覽器可能會裝有廣告攔截插件,但總有一些漏網之魚怎麼辦?沒有關係,咱們直接在瀏覽器控制檯打開 Network
, 找到廣告的地址,將該域名映射爲本地專用網絡 127.0.0.1
上。那該頁面發起的廣告請求將不能正常的獲取到資源,也是一種屏蔽廣告的好方法。
能夠作一個簡單的測試。打開 hosts
文件,修改如下映射(須要管理員權限),再打開匿名模式訪問百度首頁,而後會發現瀏覽器提示: 沒法訪問此網站 baidu.com 拒絕了咱們的鏈接請求。
127.0.0.1 localhost baidu.com ::1 localhost
修改 hosts 文件能咱們提供一些便利,但同時也要防止有人惡意篡改咱們的 hosts 文件(經過病毒等途徑),引導至詐騙網站。
hosts 文件是系統文件,直接經過路徑找 hosts 文件對於一些朋友來講感受會有點繁瑣。所以在不一樣操做系統下有開發者開發了這方面的便捷工具,如 MacOS 上能夠下載 SwitchHosts 來輔助修改,也能夠在其官網上查看它提供了哪些功能。
如今咱們迴歸主線,對以上本地 DNS 解析的優先級作一個梳理:
在地址欄輸入 URL 的主機名是域名的話,那麼瀏覽器將會調用域名解析器。這個域名解析器的優先級可能根據操做系統的不一樣會有所差別:
瀏覽器 DNS 緩存 > hosts 文件(或 hosts 文件 > 瀏覽器 DNS 緩存) > 本地 DNS 服務器 > ISP(因特網提供商) DNS 服務器
如今咱們假設瀏覽器緩存會被最早查找,正式來了解域名解析的過程:
1、 首先瀏覽器從 URL 提取出主機名,從瀏覽器 DNS 緩存中查找是否有對應的記錄。
2、 應用緩存中沒有找到記錄的話,會進一步查找 hosts 文件是否有記錄映射關係,有則中止下一步查找,並返回結果。
3、 若是前兩步驟都沒有找到對應的映射地址的話,將會向本地 DNS 服務器發送請求。如下對本步驟進行詳細講解:
要了解 DNS 查詢細節的話,那得先學習一下 DNS 的信息格式,而後咱們能夠安裝 Wireshark 捕獲請求分組來輔助學習:
安裝該軟件後,點擊開始捕獲分組並在過濾器上輸入 dns
後敲回車。接着在瀏覽器上訪問 zhihu.com
捕獲到以下數據:
從上圖選中數據報的頭部能夠看出,這是是一個 UDP/IPv4
數據報,同時數據報帶有 DNS 頭部信息。
這是一個標準的 DNS 查詢,發送端 IP 地址是 172.20.10.7
, 端口號爲臨時分配的 49246
。這個數據報發往本地 DNS 服務器 172.20.10.1
,端口號爲知名 DNS 端口 53
.
把 DNS 頭部信息與 DNS message 格式進行對比就能得知,Transaction ID
就是 佔 16 個比特位(如下單位簡稱爲位)的 ID
,其值爲 0x420a
。
flags
的標記能夠得知該 DNS 消息的狀態與類型。flags
佔 16 位,是標誌(或者說屬性)的集合,總共有十個標記。下面再補上 DNS 響應來一併講解 flags
:
Tips: DNS 協議分請求報文和響應報文。在面板上的No.
一欄中兩個箭頭表明着查詢發出與響應返回,具備對應關係。
在 Wireshark 面板下,Flags 內每一行表明着一個屬性說明,看上去仍是挺工整的。
QR(Query / Response)
佔 1 個位,表明本條消息是查詢(query, 0), 仍是響應(response, 1)。OpCode
)佔 4 位。無論是響應和查詢,全零都表明是標準查詢。AA(Authoritative Answer)
佔 1 位,表明着受權回答。這個標誌在上圖的查詢中沒有顯示出來是由於該標誌只對響應有用。TC(TrunCation)
佔 1 位,表明該消息是否是「可截斷的」。1
表明可截斷,0
爲不可截斷。RD(Recursion desired)
表示「指望遞歸」,佔 1 位,它告訴服務器執行遞歸執行。圖中查詢和響應的標誌位被設爲 1
, 意味着以遞歸方式進行查詢。RA(Recursion available)
佔 1 位,若是服務器支持遞歸查詢,將會在響應中設置該標誌。本地 DNS 服務器通常是使用迭代方式進行查詢,而根服務器僅支持迭代查詢。Z
佔 1 個比特位,該標誌是保留字段,以供將來使用。AD(Answer authenticated)
佔 1 位。若是包含的消息已受權,則該標誌位會被設爲 1
。若是禁用安全檢查,則下一個標誌位 CD
會被設置爲 1
.CD(Checking Disabled)
佔 1 位,該指示發送查詢的解析器是否能夠接受未經身份驗證的數據。設置 1
爲禁用安全檢查接受未經身份驗證的數據,設置 0
則不接受未經驗證的數據,RCODE(Response Code)
佔 4 位,表示響應的狀態碼,全零意味着沒有錯誤(Not Error)。除了 flags
外,下面還有請求數(Questions
)、回答記錄數(DNS 消息格式示意圖中的 ANCOUNT
,Wireshark 上的 Answer RRs
。其中 RRs
全稱爲 Resource Records
,也就是資源記錄)、受權記錄數(Authority RRs
)、其餘額外信息數(Additional RRs
),這些都是字面意思,不過多解釋。
在查詢與響應中,咱們能夠看到有相同的 Queries
,Queries
中有一個詢問(Querie
)。對於 DNS 查詢意味着 DNS 客戶端問 DNS 服務端問題,指望從它那邊獲得 www.zhihu.com
的 IP 地址。要求去 IN(互聯網)
類中找到 A 類型(IPv4 地址記錄)
的信息。對於 DNS 響應來講,這只是從查詢那裏拷貝過來的副本。
關於 class
能夠在下表中找到對應的含義。type
類型略龐大,筆者僅從維基百科截取其中一部分:
DNS 響應中還會有 Answers
這個屬性,表明着它對 Queries
給出的答案:
在 Answers
中有三個域名、多條記錄。
www.zhihu.com
, 它設置了 CNAME,經過別名映射到了 www.zhihu.com.dsa.dnsv1.com
中。www.zhihu.com.dsa.dnsv1.com
,從該域名的後綴能夠得知知乎使用了騰訊雲的動態加速域名(*.dsa.dnsv1.com
)。知乎在騰訊雲 DSA 控制檯接入加速域名後,系統會爲加速域名分配一個 「CNAME 域名」。隨後該域名又經過 CNAME 映射到 1442234.dsa.p23.tc.cdntip.com
。.dsa.p23.tc.cdntip.com
)。1442234.dsa.p23.tc.cdntip.com
,該域名下配置有多個 IPv4 地址,這些 IP 地址都是騰訊云爲知乎提供的加速節點。這些 IP 地址會根據接入網絡不一樣而動態變化。經過上面一系列的小步驟客戶端獲得了其中一個節點的 IP 地址,也就是 183.232.152.114
。瀏覽器拿到 IP 地址後能夠進行下一步的處理。
下面來對本地 DNS 查詢作一個簡單的總結:
www.zhihu.com
的記錄,因而將記錄做爲響應返回主機。4、 能走到步驟四意味着在本地 DNS 服務器上也沒有找到相應的記錄。這時本地 DNS 服務器不會當即反饋給客戶端它沒貨,而是將該查詢轉發至 ISP 提供的 DNS 服務器(緩存/轉發服務器。筆者使用的是移動的網絡,那就在移動的 DNS 服務器上找緩存)上查詢。
下例將經過 dig
命令來查找 DNS,使用 +trace
參數指定從根名稱服務器的委派路徑到 www.zhihu.com
的跟蹤。此例中發起查詢請求的是本地 DNS 服務器(172.20.10.1
),但在實際域名解析中多是由本地 DNS 服務器發送給 ISP DNS 服務器,再由 ISP DNS 服務器去向外查找。
順帶一提,dig
命令還可使用 @DNS服務器
指定 DNS 服務器來作進行查詢解析,如指定 google 的 DNS 服務器能夠添加參數 @8.8.8.8
。
下面仍是以默認的 DNS 服務器進行解析,dig
命令在 unix 上是讀取 /etc/resolv.conf
上的配置:
# 若想指定谷歌的 DNS 服務器,那就在命令行輸入: # dig @8.8.8.8 +trace www.zhihu.com ➜ blog git:(master) ✗ dig +trace www.zhihu.com ; <<>> DiG 9.10.6 <<>> +trace www.zhihu.com ;; global options: +cmd . 2364 IN NS k.root-servers.net. . 2364 IN NS l.root-servers.net. . 2364 IN NS c.root-servers.net. . 2364 IN NS m.root-servers.net. . 2364 IN NS i.root-servers.net. . 2364 IN NS j.root-servers.net. . 2364 IN NS h.root-servers.net. . 2364 IN NS b.root-servers.net. . 2364 IN NS f.root-servers.net. . 2364 IN NS g.root-servers.net. . 2364 IN NS e.root-servers.net. . 2364 IN NS a.root-servers.net. . 2364 IN NS d.root-servers.net. ;; Received 239 bytes from 172.20.10.1#53(172.20.10.1) in 5 ms com. 172800 IN NS l.gtld-servers.net. com. 172800 IN NS b.gtld-servers.net. com. 172800 IN NS c.gtld-servers.net. com. 172800 IN NS d.gtld-servers.net. com. 172800 IN NS e.gtld-servers.net. com. 172800 IN NS f.gtld-servers.net. com. 172800 IN NS g.gtld-servers.net. com. 172800 IN NS a.gtld-servers.net. com. 172800 IN NS h.gtld-servers.net. com. 172800 IN NS i.gtld-servers.net. com. 172800 IN NS j.gtld-servers.net. com. 172800 IN NS k.gtld-servers.net. com. 172800 IN NS m.gtld-servers.net. com. 86400 IN DS 30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766 com. 86400 IN RRSIG DS 8 1 86400 20191213050000 20191130040000 22545 . BIozVERNebmR+7eHRoc/OdIMRMWX54unL5wW9wP6t16pfJ+CKswMl8cv YFVeJv0wBBDEbh9mKan5iJqDaWzEm/ovgHWTJpP5EIuWJiV+Mi+LIhCI nw0zKYEL5QcPTIB3p6lxC5U7ngakgj4LX7eJZ8kIYocyBTZBKZHSCQh6 GCXAX6zJihuRDiFoC3OtXdhVGlrEIYeRX8FY+CUsPMLbGg4/JSeTNMH8 cFFFqw/4fbcKxq8xstRO5H40TKfFl7DtESDBahf2mjC9byjdpU5vteoH rIez3APISqKq2HJ9fBqDTkkjwkFMDy264MnGQjSSyZ3kvL/DYvV0qios 6pQVLw== ;; Received 1173 bytes from 192.5.5.241#53(f.root-servers.net) in 91 ms zhihu.com. 172800 IN NS ns3.dnsv5.com. zhihu.com. 172800 IN NS ns4.dnsv5.com. CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A NS SOA RRSIG DNSKEY NSEC3PARAM CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20191205054917 20191128043917 12163 com. ieaNZWBhpQYmsLR87RZURry7wNE+u9MlGQCA0q70qKsEWyDZ9QLQeB5f YO+KOK5xFOs6wKSYBAOg+rM+E4xKQZpg3/bBy5JSJVz1Pb6vfR1KHipW Zpqe5j0ehBJHOzTiLCauoSztU02rMIEr857hOWRzqapxZ0HKri8nm62l 1LRCrw/NMajpndWovkdqb9tMkibas/REg5yGShiFf/H3fw== 5NHJE6K0NQHV1589FOR75DMTDH32O109.com. 86400 IN NSEC3 1 1 0 - 5NHJVBH070QGDCJIE8E8GBT5KO0AER7R NS DS RRSIG 5NHJE6K0NQHV1589FOR75DMTDH32O109.com. 86400 IN RRSIG NSEC3 8 2 86400 20191204062552 20191127051552 12163 com. bS8kkx0QB2FpCHxscssiDYzIOgwj1ff1mN3+whV9CR1hWZnBWiZ51NW1 vVVBrkdOipkAkqS1mBXqQ/3FMzjhyS7BJxu3VTv83IPCh5VHi3GahGsQ xpRaMJy07bJ94jnL85U260Etzqwp6Lh/uk2lIaa39searrlHj7mz1dvr zB8zW+yfnIN3cQYVSPc+7CToo4ALJg0i9KC8aanCnHc38g== ;; Received 969 bytes from 192.12.94.30#53(e.gtld-servers.net) in 568 ms www.zhihu.com. 600 IN CNAME www.zhihu.com.dsa.dnsv1.com. zhihu.com. 86400 IN NS ns3.dnsv5.com. zhihu.com. 86400 IN NS ns4.dnsv5.com. ;; Received 137 bytes from 182.254.20.44#53(ns4.dnsv5.com) in 68 ms
在上面的日誌能夠看出,名稱解析是從右向左進行解析的。
now location: www.zhihu.com. ^
最早查找的是根名稱服務器。172.20.10.1
(本地 DNS 服務器)逐個詢問根域名服務器(根名稱服務器地址全球只有 13 個):「朋友,你知道 www.zhihu.com
的 IP 地址是什麼?」。根名稱服務器收到該詢問後,若它本身不知道關於 www.zhihu.com
的相關信息,它直接告訴發起查詢請求的 172.20.10.1
說它不清楚。那 172.20.10.1
就會詢問下一個根名稱服務器。這一個查詢過程就由遞歸解析變爲了迭代解析。
在不斷的根域名迭代查詢後,終於有根域名服務器知道咱們想要查詢域名的信息:
172.20.10.1
: "朋友,你知道 www.zhihu.com
的 IP 地址是什麼?"f.root-servers.net
: "雖然我不知道具體地址映射,但你能夠從 COM TLD
找到相關的線索。我有 COM TLD
的地址,你能夠去問問他們"now location: www.zhihu.com. ^^^^
172.20.10.1
在跟域名服務器(f.root-servers.net
)上拿到了 gTLD
服務器信息,這些服務器的名稱都是像 l.gtld-servers.net.
、b.gtld-servers.net.
的格式。
172.20.10.1
爲了獲得知足咱們的需求仍是得逐個拜訪這些頂級域名服務器(os: 沒辦法,託人辦事就是這樣的)。詢問的方式跟上面訪問根域名服務器相似,直到問到了合適的人(e.gtld-servers.net
)。
172.20.10.1
: "朋友,你知道 www.zhihu.com
的 IP 地址是什麼?"e.gtld-servers.net
: 「我這邊有 zhihu.com.
的記錄,我把它的聯繫方式給你,你問問它」。now location: www.zhihu.com. ^^^^^^^^^^
從 e.gtld-servers.net
返回了 zhihu.com.
的相關消息。但還得繼續迭代查詢 www.zhihu.com.
的消息,最終在 ns4.dnsv5.com
找到了咱們的目標信息。
雖然 172.20.10.1
拿到了 www.zhihu.com.
的信息,但它發現這是一條 CNAME
記錄,它被映射到了 www.zhihu.com.dsa.dnsv1.com.
域名上。這意味着若是 www.zhihu.com.dsa.dnsv1.com.
沒有再經過 CNAME 映射到別的域名上的話,那 172.20.10.1
想要找的 IP 地址就是 www.zhihu.com.dsa.dnsv1.com.
的 IP 地址。如有再映射,就繼續查找,直到找到沒有再被映射的域名,最後再將該結果返回。
至於爲何會映射到 www.zhihu.com.dsa.dnsv1.com.
,前文已經講解過,此處就再也不重複贅述。
now location: www.zhihu.com. ^^^^^^^^^^^^^^
從上面的幾個大步驟能夠看出:從客戶端與本地 DNS 服務器的查詢是屬於遞歸查詢,而 ISP DNS 服務器與外部 DNS 服務器之間的查詢通常都是迭代查詢。
本章參考資料:
世界上幾乎全部的 HTPP 通訊都是由 TCP/IP 承載的,TCP/IP 是全球計算機及網絡設備都在使用的一種經常使用的分組交換網絡分層。 HTTP 的鏈接實際上就是 TCP 鏈接以及其使用規則。 --《HTTP 權威指南》
緊接着,瀏覽器拿到知乎的 IP 地址(183.232.171.254
) 後, 瀏覽器取出 URL 的端口(HTTPS 的默認端口爲 443
)。
隨即瀏覽器會建立新的套接字(socket)向 183.232.171.254:443
發起 TCP
鏈接請求:
創建 TCP 鏈接時會經歷三次握手:
SYN
標記,用來表示這是一條鏈接請求。同時設置初始序列號爲 x
賦值給 Seq
(此次捕獲組的數據爲: SYN=1, Seq=0)。SYN
鏈接後,會選擇服務器初始序號 y
。同時向客戶端發送含有鏈接確認(SYN+ACK
)、Seq=0
(本例中的服務器初始序號)、Ack=1
(客戶端的序號 x + 1) 等信息的 TCP 分組。ACK=1
、Seq=1
(x+1)、Ack=1
(服務器 Ack 信息的拷貝)等字段的 TCP 分組給服務器。以上每個步驟至關因而一次握手。爲了確保鏈接雙方彼此徹底清除對方的情況(初始序列號等),那麼三次握手缺一不可。
若在第二次握手時,服務器發送的 TCP 分組因爲某些緣由致使客戶端沒有正確的接受到,此時客戶端沒有接受到第二次握手的控制信息,而服務器認爲已經正常鏈接了。這時雙方對丟失數據這一狀況是沒法感知的,鏈接就沒法創建。所以三次握手仍是必要的。
本章擴展資料:
創建起鏈接後理論上就經過 HTTP 傳輸數據啦。但因爲 HTTP
傳輸數據時報文是徹底透明的,所以知乎使用了 HTTPS
(HTTP Secure),也就是在 TCP 與 HTTP 之間多添加一層協議作加密及認證的服務。
HTTPS
使用 SSL(Secure Socket Layer)
和 TLS(Transport Layer Security)
協議,TCP 直接與 SSL/TSL
進行通訊,SSL/TSL
再與 HTTP
協議進行通訊,保障了信息的安全。
HTTPS
創建通訊須要一些過程,咱們配經過捕獲組能夠看到使用 TLSv1.2
的鏈接過程:
Client Hello
報文開始通訊,該消息包括密碼套件列表以及客戶端隨機數。Server Hello
做爲應答,該消息包括其選定的密碼套件和服務器隨機數Certificate
。Diffie-Hellman
密鑰交換。獲取客戶端和服務器的隨機數以及將用於計算會話密鑰的 DH
參數,並使用其私鑰對其進行加密,發送Server Key Exchange
。Server Hello Done
等待客戶端響應。Pre-master Secret
,發送 Client Key Exchange
。Change Cipher Spec
指示服務器使用後續的密鑰和算法加密發送後續消息。DH
協商出來的對稱密鑰加密通訊報文,發送 Encrypted Handshake Message
(finish message),若是這個報文加解密校驗成功,那麼就說明對稱祕鑰是正確的。New Session Ticket
來更新客戶端的 session ticket
。session ticket
是對話密鑰(session key)和加密方法通過加密後的信息,它由服務器生成,由客戶端儲存。Change Cipher Spec
消息,通知客戶端已更改加密規範。Encrypted Handshake Message
,完成服務器握手。本章參考資料:
經過 SSL/TSL
進行安全傳輸後,客戶端發起了 HTTP
GET
請求。服務器讀取請求後,對 HTTP 請求進行處理。
服務器會判斷請求是否合法,好比檢查 cookie
信息,看用戶是否有權訪問這個資源。再根據請求類型作相應處理,最終會將處理結果以及 HTTP
狀態碼返回給客戶端。
www.zhihu.com
是須要登陸後才能訪問的,登陸過程大體以下:
HTTP POST
提交用戶信息給服務端。set-cookie
設置 sessionID
來標識用戶是否登陸。下次客戶端請求服務器資源時,會自動攜帶這些 cookie
信息,服務器再經過 sessionID
來判斷請求的人是誰。注意,sessionID
這字段是業界公認用於標識用戶信息的字段,具體實現時也能夠換一個字段名。以上是比較通用的登陸流程,筆者沒有去抓包來驗證知乎具體的登陸方案。
咱們能夠打開瀏覽器匿名模式(此時匿名模式沒有 cookie 緩存),直接訪問 www.zhihu.com
沒有登陸信息瀏覽器會返回 302
(臨時重定向) 會被重定向 https://www.zhihu.com/signin?next=%2F
這個登陸頁上。
由此能夠看出 HTTP
狀態碼與 HTTP
方法在瀏覽器與服務器通訊之間的重要做用,下面介紹些經常使用的狀態碼與方法:
HTTP Method(方法) | 解釋 |
---|---|
GET | 該方法用來請求訪問已被 URI 識別的資源。咱們直接在瀏覽器地址上輸入合法的 URL 後,瀏覽器就會發出一個 GET 請求。 |
HEAD | 與 GET 方法相似,只不過 HEAD 只會返回頭部信息,不帶回資源實體。 |
POST | 向指定資源提交數據,請求服務器進行處理。好比提交 form 表單,提交較爲複雜的參數的。 |
PUT | 向指定資源位置上傳其最新內容。 |
DELETE | 請求服務器刪除指定資源。 |
OPTIONS | 預檢請求,該方法可以使服務器傳會資源所支持的全部請求方法。 |
HTTP
狀態碼能夠經過首位數字區分狀態碼大體是屬於什麼類型的:
HTTP status(狀態碼) | 解釋 |
---|---|
1xx | 消息 |
2xx | 成功 |
3xx | 除了 304 狀態碼,其餘大多與重定向相關 |
4xx | 客戶端錯誤 |
5xx | 服務端錯誤 |
平常工做中常見狀態碼:
HTTP status(狀態碼) | 解釋 |
---|---|
200 (ok) | 請求成功 |
301 (Move Permanently) | 永久重定向,表示這資源搬家了,你去 location: //xxx.com 能夠找到它 |
302 (Found) | 臨時重定向。該資源可能臨時出門旅遊了,你能夠先去 location: //xxx.com 看看狀況。晚些時候它也可能會回來,也可能跑路了 |
304 (Not Modified) | 客戶端發送 GET 請求時,服務器經過請求頭部信息發現請求的資源跟之前請求的那份同樣,沒有發生改變。而後服務端會返回 304 狀態碼並對客戶端說:你想要的資源跟之前同樣,你直接用緩存的文件吧,貨我就不給你,畢竟寄東西是須要郵費 |
400 (Bad Request) | 客戶端向服務器發送的請求報文中存在語法錯誤,服務器看不懂就會返回 400 狀態碼並對客戶端說: "朋友,如今我再給你一次組織語言的機會,你仔細瞧瞧是否是漏了點啥" |
401 (Unauthorized) | 未認證,客戶端向服務器請求的資源須要認證信息,客戶端沒有認證信息 |
403 (Forbidden) | 服務器已經理解請求,可是拒絕執行它。(大灰狼: "小白兔開門,我給你叔叔的妹夫的堂兄呀!我跟你爹但是熟人";小白兔:」大壞蛋,你休想騙我開門!「) |
404 (Not Found) | 請求失敗,請求所但願獲得的資源未被在服務器上發現。也有多是資源存在,但服務器不想給你就僞裝不在。(某天你想拜訪舊友,發現人家拆遷了,甚至樓都被剷平了) |
500 (Internal Server Error) | 服務器拋錯,沒法正常完成請求的處理。有可能有 bug、也多是其餘緣由 |
503 (Service Unavailable) | 因爲臨時的服務器維護或者過載,服務器當前沒法處理請求。這個情況是暫時的,而且將在一段時間之後恢復。訪問頁面遇到此錯誤多數狀況下是正在部署頁面 |
504 (Service Unavailable) | 做爲網關或者代理工做的服務器嘗試執行請求時,未能及時從上游服務器或者輔助服務器收到響應。 |
因爲筆者目前的環境上沒有屏幕錄製工具,這裏就直接用筆者之前錄製的舊圖來演示。下面是調整網絡速度後訪問掘金首頁的所發起 HTTP
加載過程:
在輸入網址後,瀏覽器向服務端發起請求,服務端會將目標資源經過 HTTP
返回,瀏覽器解析文檔時,再一次根據文檔裏的(link 或者 script 標籤)進一步請求外部資源(詳情放在下面再說).
咱們能夠在Network上看到,瀏覽器將請求發出去後,請求的status
會變爲pending
,這也是上面說到開始創建鏈接請求的第一步,正在等待服務器的迴應。隨即咱們點進請求詳情內,能夠發現請求頭只有少許的字段。
咱們再打開一個請求狀態(status)爲 200 的請求,就能看到完整的請求頭以及服務端傳回來的響應了.
擴展資料:
瀏覽器開始解析頁面,不一樣的瀏覽器引擎渲染過程都不太同樣,這裏以 webkit內核
的渲染方式爲例:
若是遇到了<script>
標籤則會中止解析文檔,這是由於 JavaScript 中可能會帶有document.write
方法,可能會重寫頁面的結構,所以瀏覽器會等待script
標籤下載完畢並執行後纔會繼續解析文檔。
這也是著名的 web 開發最佳實踐的規則之一的由來————將<script>
放在<body/>
之上,這樣就不會阻塞文檔解析了。
RenderStyle
對象中。RenderStyle
對象被RenderObject
類所管理和使用.下圖是 Mozilla
官網的頁面渲染的過程:
本篇文章是筆者去年初寫的了。因爲最近幾個月都在研究計算機底層的知識,所以想借此機會重構本篇文章。
因爲現實工做的緣故,目前只來得及對大部份內容進行重寫,本篇後期一些內容講的比較簡單,若是以後還有空的話會繼續重構。
本文主要是經過筆者現有的知識體系進行歸納性科普,如有內容表達得不對,歡迎在評論區或私信指正~若是想更深刻的學習計算機底層的知識,建議經過專業的教材進行系統的學習。本文各章下都有參考資源與推薦閱讀,有興趣的朋友能夠去了解一下。
最後歡迎讀者朋友們訂閱筆者博客。整理學習筆記不易,不點個贊鼓勵一下筆者再走嗎~
原文出自:初識網絡原理: 從瀏覽器地址欄輸入 URL 到頁面渲染之間都經歷了什麼