作者:何偉鵬鏈接:https://www.zhihu.com/question/34873227/answer/70038032來源:知乎著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
計算機網(wǎng)絡(luò)龐大且復(fù)雜,很難一言或幾言以蔽之。因此,這里我們只考慮最一般的場景,所謂“一般”,就是...比如,沒有緩存,客戶機和服務(wù)器不在一個局域網(wǎng),輸入的是一個域名而不是IP地址,etc。我們采用自頂向下的方法,也是時間順序的方法,來解答這個問題。瀏覽器是C/S架構(gòu)中的客戶端,通過想服務(wù)器發(fā)送請求,獲取文件(html,js,css等),再通過瀏覽器引擎的解釋和渲染,將這些文件呈現(xiàn)成你現(xiàn)在看到的樣子。1、TCP/IP參考模型首先,我們不得不了解一下TCP/IP參考模型。如下圖所示,TCP/IP參考模型分為四層:應(yīng)用層、運輸層、網(wǎng)絡(luò)層和接口層。瀏覽器所完成的工作就屬于應(yīng)用層的范疇。

應(yīng)用層: 為用戶提供各種服務(wù),比如我們?yōu)g覽網(wǎng)頁時用到的HTTP,收發(fā)郵件時用的SMTP,登錄遠程主機用的SSH。
傳輸層:提供端到端的傳輸服務(wù)。更具體地講,提供進程到進程的傳輸服務(wù)。
網(wǎng)絡(luò)層:和傳輸層一樣,可以概括為提供端到端的傳輸服務(wù)。更具體地講,網(wǎng)絡(luò)層提供主機到主機的傳輸服務(wù)。
網(wǎng)絡(luò)接口層(鏈路層):為直接連接的設(shè)備提供傳輸服務(wù),將數(shù)據(jù)幀轉(zhuǎn)換為比特流,并將比特流轉(zhuǎn)換為物理電路的電壓高低信號。
2、往哪里發(fā)送請求?假設(shè)我么輸入的地址是zhihu.com
瀏覽器看到這個域名的時候,就好像我們想去一家從沒去過的餐廳吃飯,只知道名字是“黃大仙腸粉”但不知道具體地點在哪里。這個時候,我們打開地圖,搜索“黃大仙腸粉”后找到一個地址:衡山路110號,于是我們便知道該去哪了。域名就像是一個餐廳的名字,而IP地址相當于一個具體的地址。瀏覽器必須知道所請求服務(wù)器的IP地址,發(fā)出的請求才有目的地。DNS(Domain Name System)提供的服務(wù)就是將知乎的域名轉(zhuǎn)換成其服務(wù)器IP地址。DNS具有兩層含義:①一個由分層的DNS服務(wù)器實現(xiàn)的分布式數(shù)據(jù)庫;②一個允許主機查詢分布式數(shù)據(jù)庫的應(yīng)用層協(xié)議。有三種類型的DNS服務(wù)器:根DNS服務(wù)器、頂級DNS服務(wù)器和權(quán)威DNS服務(wù)器。這些服務(wù)器以下圖的層次結(jié)構(gòu)組織起來。除此之外,還有一類重要的DNS,稱為本地DNS服務(wù)器。嚴格來說本地DNS服務(wù)器并不屬于DNS服務(wù)器的層次結(jié)構(gòu),但它在整個查詢的過程中卻扮演著重要的角色。



TCP是面向連接的,在實際發(fā)送數(shù)據(jù)之前,客戶端和服務(wù)器需要建立起一個TCP連接。這種TCP“連接”只是邏輯上的鏈接,因為其狀態(tài)完全保留在兩個端系統(tǒng)中,中間路由器對TCP連接毫不知情。



目的端口和源端口號是為了在多路復(fù)用和多路分解時選擇套接字時使用的。數(shù)據(jù)序號和確認序號是為了傳輸數(shù)據(jù)的完整性和順序而設(shè)置的。用戶數(shù)據(jù)這一個字段就存儲了應(yīng)用層生成的HTTP報文。ACK、SYN和FIN是在建立連接和關(guān)閉連接時使用。其他用于流量控制、擁塞管理等用途的字符就不展開了。5、路由尋址現(xiàn)在兩個端系統(tǒng)已經(jīng)建立起了連接,請求也被傳送到客戶端主機的網(wǎng)絡(luò)層。網(wǎng)絡(luò)層是協(xié)議棧中最復(fù)雜的層次,應(yīng)用層和傳輸層只運行在兩個端系統(tǒng),而網(wǎng)絡(luò)層不僅運行在端系統(tǒng),還運行在各個中間節(jié)點上。我們先來看看IP數(shù)據(jù)報的格式。網(wǎng)絡(luò)層實現(xiàn)的最重要的功能是路由選擇,簡單地說,就是怎么把這一個IP數(shù)據(jù)報從客戶端主機出發(fā),通過網(wǎng)絡(luò)中的若干個路由器,到達目的主機。從概念上講,IP路由選擇是簡單的,特別對于主機來說,如果目的主機和源主機直接相連(如點對點鏈路),或都在一個共享網(wǎng)絡(luò)上(以太網(wǎng)或令牌環(huán)網(wǎng)),那么IP數(shù)據(jù)報就直接送到目的主機上。否則,主機把數(shù)據(jù)報發(fā)送到一默認的路由器上,由路由器來轉(zhuǎn)發(fā)該數(shù)據(jù)報。大多數(shù)的主機都采用這種簡單機制。


搜索路由表,尋找能與目標網(wǎng)絡(luò)號相匹配的表目。如果找到,則把報文發(fā)送給下一跳節(jié)點。
搜索路由表,尋找“默認”的表目。如果找到,則把報文發(fā)送給下一跳節(jié)點。
如果上面這些步驟都沒有成功,那么該數(shù)據(jù)報就不能被傳送。如果不能傳送的數(shù)據(jù)報來自本機,那么一般會向生成數(shù)據(jù)報的應(yīng)用程序返回一個“主機不可達”或“網(wǎng)絡(luò)不可達”的錯誤。在我們的例子中,H1通過搜索自己的路由表將數(shù)據(jù)報轉(zhuǎn)發(fā)給R1,R1根據(jù)路由表轉(zhuǎn)發(fā)給R2,最后到達H2。6、關(guān)閉連接目標主機收到了請求后,自底向上地對該請求進行處理。鏈路層把數(shù)據(jù)報傳給網(wǎng)絡(luò)層,網(wǎng)路層將TCP數(shù)據(jù)段通過對應(yīng)的Socket傳給應(yīng)用程序。應(yīng)用程序處理請求后產(chǎn)生一個應(yīng)答的HTTP報文,又經(jīng)過了一層層的封裝、一跳跳的傳輸?shù)竭_了源主機。這樣就結(jié)束了嗎?那一條TCP連接還沒有關(guān)閉呢,源主機和目標主機上都為它分配了資源呢,如果不釋放掉的話資源很快就會耗盡(DDoS攻擊就是利用這一點)。于是,當傳輸層收到了應(yīng)答之后,就要關(guān)閉這條連接了。但是,又不能悄悄地自己關(guān)了,目標主機那邊還不知道你要不要關(guān)閉呢。于是乎,就有了對應(yīng)創(chuàng)建TCP連接“三次握手”的關(guān)閉TCP連接“四次揮手”。如下圖所示,客戶端向服務(wù)器發(fā)出了FIN報文段,服務(wù)器收到后,回復(fù)一個ACK應(yīng)答。然后,服務(wù)器也向客戶端發(fā)送一個FIN報文段,隨后關(guān)閉了服務(wù)器端的連接,釋放了資源。當客戶端收到之后,又向服務(wù)器回復(fù)一個ACK應(yīng)答。過了一段計時等待,客戶端也關(guān)閉了連接,釋放資源。這一段計時等待的時間是為了客戶端重傳最后的ACK防止其丟失。

剩下的事情,就交給瀏覽器了。