當(dāng)前位置:首頁 > 新聞中心 > 互聯(lián)網(wǎng)動(dòng)態(tài)
計(jì)算機(jī)牛人為你圖解:url與網(wǎng)站背后的關(guān)系責(zé)任編輯 :李飛    文章來源 :星翼創(chuàng)想(16qt59sf.cn)    發(fā)布時(shí)間 :2015-10-12    閱讀次數(shù):4622

以前,人們?yōu)g覽網(wǎng)頁,經(jīng)常是通過搜索,或者是一些網(wǎng)址導(dǎo)航來點(diǎn)進(jìn)去。但現(xiàn)在,經(jīng)常上網(wǎng)的人,都應(yīng)該能記得住幾個(gè)網(wǎng)址了,他們也學(xué)會(huì)了在瀏覽器的地址欄里直接輸入網(wǎng)站的url來直接訪問網(wǎng)站。但往往沒有人會(huì)去研究為什么在瀏覽器里輸入url就能訪問網(wǎng)站呢?這是一個(gè)神奇而又復(fù)雜的過程,想知道url與網(wǎng)站背后的關(guān)系?通過閱讀深圳市星翼創(chuàng)想網(wǎng)絡(luò)科技有限公司(專業(yè)的網(wǎng)站建設(shè)公司)選摘的這篇文章,你就可以了解一些基礎(chǔ)的計(jì)算機(jī)只是了。萬一跟人談及這個(gè),你的形象會(huì)瞬間變得高大上哦!


第一個(gè)問題:從輸入 URL 到瀏覽器接收的過程中發(fā)生了什么事情?

從觸屏到 CPU

首先是「輸入 URL」,大部分人的第一反應(yīng)會(huì)是鍵盤,不過為了與時(shí)俱進(jìn),這里將介紹觸摸屏設(shè)備的交互。

觸摸屏一種傳感器,目前大多是基于電容(Capacitive)來實(shí)現(xiàn)的,以前都是直接覆蓋在顯示屏上的,不過最近出現(xiàn)了 3 種嵌入到顯示屏中的技術(shù),第一種是 iPhone 5 的 In-cell,它能減小了 0.5 毫米的厚度,第二種是三星使用的 On-cell 技術(shù),第三種是國(guó)內(nèi)廠商喜歡用的 OGS 全貼合技術(shù)。

當(dāng)手指在這個(gè)傳感器上觸摸時(shí),有些電子會(huì)傳遞到手上,從而導(dǎo)致該區(qū)域的電壓變化,觸摸屏控制器芯片根據(jù)這個(gè)變化就能計(jì)算出所觸摸的位置,然后通過總線接口將信號(hào)傳到 CPU 的引腳上。

以 Nexus 5 為例,它所使用的觸屏控制器是 Synaptics S3350B,總線接口為 I2C,以下是 Synaptics 觸摸屏和處理器連接的示例:

頁面加載 網(wǎng)站響應(yīng)流程 網(wǎng)站URL

左邊是處理器,右邊是觸摸屏控制器,中間的 SDA 和 SCL 連線就是 I2C 總線接口。

CPU 內(nèi)部的處理

移動(dòng)設(shè)備中的 CPU 并不是一個(gè)單獨(dú)的芯片,而是和 GPU 等芯片集成在一起,被稱為 SoC(片上系統(tǒng))。

前面提到了觸屏和 CPU 的連接,這個(gè)連接和大部分計(jì)算機(jī)內(nèi)部的連接一樣,都是通過電氣信號(hào)來進(jìn)行通信的,也就是電壓高低的變化,如下面的時(shí)序圖:

頁面加載 網(wǎng)站響應(yīng)流程 網(wǎng)站URL

在時(shí)鐘的控制下,這些電流會(huì)經(jīng)過 MOSFET 晶體管,晶體管中包含 N 型半導(dǎo)體和 P 型半導(dǎo)體,通過電壓就能控制線路開閉,然后這些 MOSFET 構(gòu)成了 CMOS,接著再由 CMOS 實(shí)現(xiàn)「與」「或」「非」等邏輯電路門,最后由邏輯電路門上就能實(shí)現(xiàn)加法、位移等計(jì)算,整體如下圖所示(來自《計(jì)算機(jī)體系結(jié)構(gòu)》):

頁面加載 網(wǎng)站響應(yīng)流程 網(wǎng)站URL

除了計(jì)算,在 CPU 中還需要存儲(chǔ)單元來加載和存儲(chǔ)數(shù)據(jù),這個(gè)存儲(chǔ)單元一般通過觸發(fā)器(Flip-flop)來實(shí)現(xiàn),稱為寄存器。

以上這些概念都比較抽象,推薦閱讀「How to Build an 8-Bit Computer」這篇文章,作者基于晶體管、二極管、電容等原件制作了一個(gè) 8 位的計(jì)算機(jī),支持簡(jiǎn)單匯編指令和結(jié)果輸出,雖然現(xiàn)代 CPU 的實(shí)現(xiàn)要比這個(gè)復(fù)雜得多,但基本原理還是一樣的。

另外其實(shí)我也是剛開始學(xué)習(xí) CPU 芯片的實(shí)現(xiàn),所以就不在這誤人子弟了,感興趣的讀者請(qǐng)閱讀本節(jié)后面推薦的書籍。

從 CPU 到操作系統(tǒng)內(nèi)核

前面說到觸屏控制器將電氣信號(hào)發(fā)送到 CPU 對(duì)應(yīng)的引腳上,接著就會(huì)觸發(fā) CPU 的中斷機(jī)制,以 Linux 為例,每個(gè)外部設(shè)備都有一標(biāo)識(shí)符,稱為中斷請(qǐng)求(IRQ)號(hào),可以通過 /proc/interrupts 文件來查看系統(tǒng)中所有設(shè)備的中斷請(qǐng)求號(hào),以下是 Nexus 7 (2013) 的部分結(jié)果:

shell@flo:/$cat/proc/interrupts
            CPU0
  17:          0       GIC  dg_timer
294:    1973609   msmgpio  elan-ktf3k
314:        679   msmgpio  KEY_POWER

因?yàn)?Nexus 7 使用了 ELAN 的觸屏控制器,所以結(jié)果中的 elan-ktf3k 就是觸屏的中斷請(qǐng)求信息,其中 294 是中斷號(hào),1973609 是觸發(fā)的次數(shù)(手指單擊時(shí)會(huì)產(chǎn)生兩次中斷,但滑動(dòng)時(shí)會(huì)產(chǎn)生上百次中斷)。

為了簡(jiǎn)化這里不考慮優(yōu)先級(jí)問題,以 ARMv7 架構(gòu)的處理器為例,當(dāng)中斷發(fā)生時(shí),CPU 會(huì)停下當(dāng)前運(yùn)行的程序,保存當(dāng)前執(zhí)行狀態(tài)(如 PC 值),進(jìn)入 IRQ 狀態(tài)),然后跳轉(zhuǎn)到對(duì)應(yīng)的中斷處理程序執(zhí)行,這個(gè)程序一般由第三方內(nèi)核驅(qū)動(dòng)來實(shí)現(xiàn),比如前面提到的 Nexus 7 的驅(qū)動(dòng)源碼在這里 touchscreen/ektf3k.c

這個(gè)驅(qū)動(dòng)程序?qū)⒆x取 I2C 總線中傳來的位置數(shù)據(jù),然后通過內(nèi)核的 input_report_abs 等方法記錄觸屏按下坐標(biāo)等信息,最后由內(nèi)核中的input 子模塊將這些信息都寫進(jìn) /dev/input/event0 這個(gè)設(shè)備文件中,比如下面展示了一次觸摸事件所產(chǎn)生的信息:

130|shell@flo:/$getevent-lt/dev/input/event0
[  414624.658986]EV_ABS       ABS_MT_TRACKING_ID   0000835c
[  414624.659017]EV_ABS       ABS_MT_TOUCH_MAJOR   0000000b
[  414624.659047]EV_ABS       ABS_MT_PRESSURE      0000001d
[  414624.659047]EV_ABS       ABS_MT_POSITION_X    000003f0
[  414624.659078]EV_ABS       ABS_MT_POSITION_Y    00000588
[  414624.659078]EV_SYN       SYN_REPORT           00000000
[  414624.699239]EV_ABS       ABS_MT_TRACKING_ID   ffffffff
[  414624.699270]EV_SYN       SYN_REPORT           00000000

 從操作系統(tǒng) GUI 到瀏覽器

前面提到 Linux 內(nèi)核已經(jīng)完成了對(duì)硬件的抽象,其它程序只需要通過監(jiān)聽 /dev/input/event0 文件的變化就能知道用戶進(jìn)行了哪些觸摸操作,不過如果每個(gè)程序都這么做實(shí)在太麻煩了,所以在圖像操作系統(tǒng)中都會(huì)包含 GUI 框架來方便應(yīng)用程序開發(fā),比如 Linux 下著名的 X。

但 Android 并沒有使用 X,而是自己實(shí)現(xiàn)了一套 GUI 框架,其中有個(gè) EventHub 的服務(wù)會(huì)通過 epoll 方式監(jiān)聽 /dev/input/ 目錄下的文件,然后將這些信息傳遞到 Android 的窗口管理服務(wù)(WindowManagerService)中,它會(huì)根據(jù)位置信息來查找相應(yīng)的 app,然后調(diào)用其中的監(jiān)聽函數(shù)(如 onTouch 等)。

就這樣,我們解答了第一個(gè)問題,不過由于時(shí)間有限,這里省略了很多細(xì)節(jié)。

第二個(gè)問題:瀏覽器如何向網(wǎng)卡發(fā)送數(shù)據(jù)?

從瀏覽器到瀏覽器內(nèi)核

前面提到操作系統(tǒng) GUI 將輸入事件傳遞到了瀏覽器中,在這過程中,瀏覽器可能會(huì)做一些預(yù)處理,比如 Chrome 會(huì)根據(jù)歷史統(tǒng)計(jì)來預(yù)估所輸入字符對(duì)應(yīng)的網(wǎng)站,比如輸入了「ba」,根據(jù)之前的歷史發(fā)現(xiàn) 90% 的概率會(huì)訪問「www.baidu.com 」,因此就會(huì)在輸入回車前就馬上開始建立 TCP 鏈接甚至渲染了,這里面還有很多其它策略,感興趣的讀者推薦閱讀  High Performance Networking in Chrome。

接著是輸入 URL 后的「回車」,這時(shí)瀏覽器會(huì)對(duì) URL 進(jìn)行檢查,首先判斷協(xié)議,如果是 http 就按照 Web 來處理,另外還會(huì)對(duì)這個(gè) URL 進(jìn)行安全檢查,然后直接調(diào)用瀏覽器內(nèi)核中的對(duì)應(yīng)方法,比如 WebView 中的 loadUrl 方法。

在瀏覽器內(nèi)核中會(huì)先查看緩存,然后設(shè)置 UA 等 HTTP 信息,接著調(diào)用不同平臺(tái)下網(wǎng)絡(luò)請(qǐng)求的方法。

 

需要注意瀏覽器和瀏覽器內(nèi)核是不同的概念,瀏覽器指的是 Chrome、Firefox,而瀏覽器內(nèi)核則是 Blink、Gecko,瀏覽器內(nèi)核只負(fù)責(zé)渲染,GUI 及網(wǎng)絡(luò)連接等跨平臺(tái)工作則是瀏覽器實(shí)現(xiàn)的

HTTP 請(qǐng)求的發(fā)送

因?yàn)榫W(wǎng)絡(luò)的底層實(shí)現(xiàn)是和內(nèi)核相關(guān)的,所以這一部分需要針對(duì)不同平臺(tái)進(jìn)行處理,從應(yīng)用層角度看主要做兩件事情:通過 DNS 查詢 IP、通過 Socket 發(fā)送數(shù)據(jù),接下來就分別介紹這兩方面的內(nèi)容。

DNS 查詢

應(yīng)用程序可以直接調(diào)用 Libc 提供的 getaddrinfo() 方法來實(shí)現(xiàn) DNS 查詢。

DNS 查詢其實(shí)是基于 UDP 來實(shí)現(xiàn)的,這里我們通過一個(gè)具體例子來了解它的查找過程,以下是使用 dig +trace fex.baidu.com 命令得到的結(jié)果(省略了一些):

;<<>>DiG9.8.3-P1<<>>+trace fex.baidu.com
;;globaloptions:+cmd
.           11157   IN  NS  g.root-servers.net.
.           11157   IN  NS  i.root-servers.net.
.           11157   IN  NS  j.root-servers.net.
.           11157   IN  NS  a.root-servers.net.
.           11157   IN  NS  l.root-servers.net.
;;Received228bytes from8.8.8.8#53(8.8.8.8) in 220 ms
 
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  e.gtld-servers.net.
;;Received503bytes from192.36.148.17#53(192.36.148.17) in 185 ms
 
baidu.com.      172800  IN  NS  dns.baidu.com.
baidu.com.      172800  IN  NS  ns2.baidu.com.
baidu.com.      172800  IN  NS  ns3.baidu.com.
baidu.com.      172800  IN  NS  ns4.baidu.com.
baidu.com.      172800  IN  NS  ns7.baidu.com.
;;Received201bytes from192.48.79.30#53(192.48.79.30) in 1237 ms
 
fex.baidu.com.      7200    IN  CNAME   fexteam.duapp.com.
fexteam.duapp.com.  300IN  CNAME   duapp.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns1.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns4.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns2.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns5.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns3.n.shifen.com.
;;Received258bytes from61.135.165.235#53(61.135.165.235) in 2 ms

可以看到這是一個(gè)逐步縮小范圍的查找過程,首先由本機(jī)所設(shè)置的 DNS 服務(wù)器(8.8.8.8)向 DNS 根節(jié)點(diǎn)查詢負(fù)責(zé) .com 區(qū)域的域務(wù)器,然后通過其中一個(gè)負(fù)責(zé) .com 的服務(wù)器查詢負(fù)責(zé) baidu.com 的服務(wù)器,最后由其中一個(gè) baidu.com 的域名服務(wù)器查詢 fex.baidu.com 域名的地址。

可能你在查詢某些域名的時(shí)會(huì)發(fā)現(xiàn)和上面不一樣,最底將看到有個(gè)奇怪的服務(wù)器搶先返回結(jié)果。。。

 

這里為了方便描述,忽略了很多不同的情況,比如 127.0.0.1 其實(shí)走的是 loopback,和網(wǎng)卡設(shè)備沒關(guān)系;比如 Chrome 會(huì)在瀏覽器啟動(dòng)的時(shí)預(yù)先查詢 10 個(gè)你有可能訪問的域名;還有 Hosts 文件、緩存時(shí)間 TTL(Time to live)的影響等。

通過 Socket 發(fā)送數(shù)據(jù)

有了 IP 地址,就可以通過 Socket API 來發(fā)送數(shù)據(jù)了,這時(shí)可以選擇 TCP 或 UDP 協(xié)議,具體使用方法這里就不介紹了,推薦閱讀 Beej’s Guide to Network Programming。

HTTP 常用的是 TCP 協(xié)議,由于 TCP 協(xié)議的具體細(xì)節(jié)到處都能看到,所以本文就不介紹了,這里談一下 TCP 的 Head-of-line blocking 問題:假設(shè)客戶端的發(fā)送了 3 個(gè) TCP 片段(segments),編號(hào)分別是 1、2、3,如果編號(hào)為 1 的包傳輸時(shí)丟了,即便編號(hào) 2 和 3 已經(jīng)到達(dá)也只能等待,因?yàn)?TCP 協(xié)議需要保證順序,這個(gè)問題在 HTTP pipelining 下更嚴(yán)重,因?yàn)?HTTP pipelining 可以讓多個(gè) HTTP 請(qǐng)求通過一個(gè) TCP 發(fā)送,比如發(fā)送兩張圖片,可能第二張圖片的數(shù)據(jù)已經(jīng)全收到了,但還得等第一張圖片的數(shù)據(jù)傳到。

為了解決 TCP 協(xié)議的性能問題,Chrome 團(tuán)隊(duì)去年提出了 QUIC 協(xié)議,它是基于 UDP 實(shí)現(xiàn)的可靠傳輸,比起 TCP,它能減少很多來回(round trip)時(shí)間,還有前向糾錯(cuò)碼(Forward Error Correction)等功能。目前 Google Plus、 Gmail、Google Search、blogspot、Youtube 等幾乎大部分 Google 產(chǎn)品都在使用 QUIC,可以通過 chrome://net-internals/#spdy 頁面來發(fā)現(xiàn)。

雖然目前除了 Google 還沒人用 QUIC,但我覺得挺有前景的,因?yàn)閮?yōu)化 TCP 需要升級(jí)系統(tǒng)內(nèi)核(比如 Fast Open)。

 

瀏覽器對(duì)同一個(gè)域名有連接數(shù)限制,大部分是 6,我以前認(rèn)為將這個(gè)連接數(shù)改大后會(huì)提升性能,但實(shí)際上并不是這樣的,Chrome 團(tuán)隊(duì)有做過實(shí)驗(yàn),發(fā)現(xiàn)從 6 改成 10 后性能反而下降了,造成這個(gè)現(xiàn)象的因素有很多,如建立連接的開銷、擁塞控制等問題,而像 SPDY、HTTP 2.0 協(xié)議盡管只使用一個(gè) TCP 連接來傳輸數(shù)據(jù),但性能反而更好,而且還能實(shí)現(xiàn)請(qǐng)求優(yōu)先級(jí)。

另外,因?yàn)?HTTP 請(qǐng)求是純文本格式的,所以在 TCP 的數(shù)據(jù)段中可以直接分析 HTTP 的文本,如果發(fā)現(xiàn)。。。

Socket 在內(nèi)核中的實(shí)現(xiàn)

前面說到瀏覽器的跨平臺(tái)庫(kù)通過調(diào)用 Socket API 來發(fā)送數(shù)據(jù),那么 Socket API 是如何實(shí)現(xiàn)的呢?

以 Linux 為例,它的實(shí)現(xiàn)在這里 socket.c,目前我還不太了解,推薦讀者看看 Linux kernel map,它標(biāo)注出了關(guān)鍵路徑的函數(shù),方便學(xué)習(xí)從協(xié)議棧到網(wǎng)卡驅(qū)動(dòng)的實(shí)現(xiàn)。

底層網(wǎng)絡(luò)協(xié)議的具體例子

接下來如果繼續(xù)介紹 IP 協(xié)議和 MAC 協(xié)議可能很多讀者會(huì)暈,所以本節(jié)將使用 Wireshark 來通過具體例子講解,以下是我請(qǐng)求百度首頁時(shí)抓取到的網(wǎng)絡(luò)數(shù)據(jù):

頁面加載 網(wǎng)站響應(yīng)流程 網(wǎng)站URL

最底下是實(shí)際的二進(jìn)制數(shù)據(jù),中間是解析出來的各個(gè)字段值,可以看到其中最底部為 HTTP 協(xié)議(Hypertext Transfer Protocol),在 HTTP 之前有 54 字節(jié)(0×36),這就是底層網(wǎng)絡(luò)協(xié)議所帶來的開銷,我們接下來對(duì)這些協(xié)議進(jìn)行分析。

在 HTTP 之上是 TCP 協(xié)議(Transmission Control Protocol),它的具體內(nèi)容如下圖所示:

頁面加載 網(wǎng)站響應(yīng)流程 網(wǎng)站URL



文章轉(zhuǎn)載請(qǐng)保留網(wǎng)址:http://16qt59sf.cn/news/industry/1508.html

掃碼添加微信
159 8667 8737
24小時(shí)電話

返回頂部