網絡相關的知識是每一個前端工程師都應該具有的。不少從事前端的朋友們都沒系統學習過計算機網絡和http相關內容。在沒有創建一個總體的知識體系下,會有一種一站到底答題的感受,每一個知識點都大體知道問題的答案,但總不肯定,更不知道具體是怎麼回事。本文系統的梳理了與前端密切相關的網絡知識。(這是我本身學習的總結,整理出的筆記,分享給你們)html
本文中的代碼演示整理在《node.js的小美好》 :前端
仍是老規則,在學以前,咱們先考考本身,我整理一下知識點,看看咱們須要掌握那些問題。而後咱們經過把問題知識點串起來去總結。node
必會:git
基礎:github
補課與拓展:(慢慢更新)web
必會是和前端工做中聯繫最緊密的http協議相關的內容。可是若是沒有網絡基礎,就好像空中樓閣。沒法創建起知識體系。因此本文會把必會和基礎放到一塊兒,也就是本文的1-5章內容。ajax
補課與擴展:而深刻學習下一代QUIC就必須瞭解TCP和UDP的具體工做原理。因此這裏會給你們偷偷補課。一些經常使用的拓展內容也會放到後邊幾章。算法
本文會用node作代碼演示,相關代碼在github上。若是node基礎很差的同窗,我把本章全部的代碼整理成了一篇node的學習文檔。《node.js的小美好》 。每一小節會有一些習題,用來鞏固複習,我慢慢加。chrome
咱們從第一題開始,當瀏覽器訪問www.jd.com時,咱們都知道瀏覽器向服務器發送了http請求,會把請求報文發送給服務器。那麼我先粗略分析一下這個過程。json
瀏覽器會基於http協議產生一個http報文(消息),而後會把這個報文拆分紅不一樣的分組(包)。發送到路由上。路由先進行緩存,而後在根據路由錶轉發給下一個路由,直到到達服務器。
客戶端 ---> 路由--->路由.......----> 路由--->服務器
複製代碼
咱們爲何不直接把消息發送給服務器,爲何必定要分包呢?
首先,路由是先緩存再轉發,若是把整個報文直接發給服務器,那麼對路由內存要求會很是高。另外還有一個重要的概念就是網絡的帶寬,也是在鏈路上的傳輸速率,它是由單位時間內能夠傳輸的數據總量決定的。而不是咱們物理距離,舉個例子。
(1)基礎題 (來自《阿里技術之瞳》)
使用一輛卡車運輸n塊裝滿數據的1TB硬盤,以80km/h速度行駛1000km將數據運送到目的地,
卡車至少運送多少塊硬盤才能使傳輸速率超過1000Gbit/s?
答案:5625
解析:這個問題能夠簡化成兩種方案在相同時間內兩種方案要傳輸相同的數據量。
卡車的時間爲: 1000km ÷ 80Km = 12.5h
在相同時間內網絡傳輸的數據量爲: 12.5h * 3600s/h * 1000Gbit/s ÷ 8b/B = 5625000GB.
那麼卡車須要運輸相同的運算量,5625000GB ÷ 1000GB = 5625塊。
總結:帶寬:在鏈路上的傳輸速率(bit/sec 即 bps)
bit(位) // 1 Byte = 8 bit
複製代碼
拓展:那麼咱們如今分析一下交付時間
如今有一個5Mbits的報文,在寬帶是1Mbps,從客戶端C1 發送到 服務器h2,通過路由器A,B。忽略其餘影響。
C1---> A ----> B ---- h2
一次報文交換交付時間:
C1---> A : 5Mbits / 1Mbps = 5s
A ---> B : 5Mbits / 1Mbps = 5s
B --->h2 : 5Mbits / 1Mbps = 5s
共15s
若是分紅5000組 , 那麼每一個包是1bits。
H1---> A : 1bits / 1Mbps = 1ms
當第1個到達時A時須要1ms,第2個已經出發
當第2個已經到A時,第1個已經到達B
當第5000個到達A時,第4999個到底B,其他都到達。這時候用時5s
當第5000個到達h2時,就用時,5秒零2毫秒。
最後總結一下:
- 報文:M bits
- 鏈路寬帶:R bps
- 路由器數:n
- 分組長度:L bits
- 一次報文交換交付時間 : T = (n+1) * (M / R)
- 分組交換報文交付時間:T = M / R + nL/R
複製代碼
因此能夠看出分組交換比一次報文交互性能要好。而上面所用的時間就叫做傳輸延遲
傳輸延遲是影響網速的最主要緣由,那麼還有一些影響網速的緣由咱們來看看:
問題:如今咱們粗略瞭解了這個過程,那麼具體都經歷那些過程呢?
咱們先看來看OSI解釋的七成參考模型。
因此這也符合咱們函數的模塊化,低層函數定義好接口API,你按照函數的接口文檔去調用依賴的函數,而後就等着讓它去處理。在實際的開發中,咱們就是這麼去實現的。
每一層經過本層的協議,增長控制信息,構造協議數據單元PUD。
應用層:
傳輸層:
網絡層:
鏈路層:
物理層:
因此如今咱們知道了,每發送一個http請求,是針對應用層的請求和響應。應用層雖然來回只有一次。但它下面傳輸層,要把整個報文,分紅許多分組,再交給下一層,著名的TCP三次連接就是指的傳輸層的。因此應用層的一次請求和響應,再鏈路是可能要走許屢次。每一個包確定是確定擁有每一個層的協議,不可能只有上層沒有下層。而咱們常說的數據包,就應該是一個段(分組)通過處理成,最後變成比特在鏈路上傳輸。
你會發現咱們並無講表示層和會話層?由於
應用層 和 傳輸層 咱們後邊都會詳細講。這裏咱們再講一下 網絡層,鏈路層,物理層。
上面咱們知道,物理層會把比特在物理介質上傳輸。那麼主機可能和多臺電腦相連,那麼二進制碼怎麼會知道 這是發個那臺電腦,走那條網線呢?
咱們知道在鏈路層會加上要訪問主機的物理尋址(MAC地址),因此若是網線連多個電腦,會送到每臺電腦,在物理層轉化回幀,發現若是不是目標電腦的Mac地址,就不去處理。直到找到目標Mac地址的電腦。這裏用到的就是MAC協議。
那麼鏈路層是怎麼知道目標機器的Mac地址的呢?
在網絡層,咱們知道了要訪問服務器的IP,首先操做系統會判斷是否是本地IP,若是不是,會發送給網關。 操做系統啓動的時候,就會被 DHCP 協議配置 IP 地址,以及默認的網關的 IP 地址 192.168.1.1。 操做系統會廣播,誰是 192.168.1.1 啊?網關會回答它,我就是,這是Mac地址。這樣咱們就知道了Mac 地址。這個廣播獲得Mac 地址的協議就是ARP協議。
網關每每是一個路由器,知道到某個 IP 地址應該怎麼走,這個叫做路由表。這樣它再從幀中取出數據報,看到了你想去的IP,它就會告訴你那你應該走那條路,並去找哪一個路由。而後在鏈路層封裝的幀中寫入那個路由的Mac地址。
路由是怎麼知道怎麼走的呢,由於路由和路由也會溝通。溝通的協議稱爲路由協議,經常使用的有OSPF和BGP。
(測試題1)不定選項 七層網絡協議(來自京東2018秋招筆試題)
用瀏覽器訪問www.jd.com時,可能使用到的協議有?
A MAC
B HTTP
C SMTP
D ARP
E RTSP
答案:A B D
解析:因此在第一題中 HTTP是在應用層用的協議 。
MAC和ARP是在數據鏈路層用和網絡層用到的協議。
而一樣的應用層協議SMTP是郵件傳輸協議,RTSP是實時流傳輸協議。
在訪問www.jd.com的時候,咱們用不到。
複製代碼
應用層是基於傳輸層協議之上。常見的傳輸層協議有TCP,UDP。
應用層的功能是完成客戶端和服務器消息交換。要想完成信息交換就必須知道資源的位置,那咱們是怎麼約定資源位置的呢。
語法爲:
協議://用戶名:密碼@子域名.域名.頂級域名:端口號/目錄/文件名.文件後綴?參數=值#標誌
http://username:password@host:80/directory/file.html?query#ref
ftp://username:password@host:21/directory/file.html
news://news.newsgroup.com.hk
複製代碼
注意:
若是參數裏邊有!,%,&,/,?,=,等非西歐字符 須要encode 方法對url的進行預處理
應用層的功能是完成客戶端和服務器消息交換。
這時咱們會過頭來看,瀏覽器左下角,是否是一直在顯示等待響應,是由於咱們尚未返回數據啊,那咱們給 它返回一些數據。
這裏咱們先不用管TCP的細節部分,咱們會在傳輸層部分去講。
問題:在大體瞭解了應用層協議後,就讓咱們去具體學習http協議吧
這一節的內容,但是前端的看家本領,你們必定要對應着代碼本身敲出來,看看效果
HTTP報文:用於HTTP協議交互的信息被稱爲HTTP報文。
咱們那上一節以響應報文爲例,咱們以前說要符合http協議的規則,那麼http規則是什麼呢?
let responseDataTpl = `HTTP/1.1 200 OK
Connection:keep-alive
Date: ${new Date()}
Content-Length: 12
Content-Type: text/plain
Hello world!
`;
複製代碼
報文首部:根據實際用途會分爲四種
因此在chrome的network中,header會顯示爲:
實體首部字段會寫進請求頭和響應頭 對於get請求後邊的參數會顯示在Query String Parameters
在上邊TCP服務器中,咱們發現每次寫符合http協議格式的響應報文很是麻煩,爲何咱們不封裝好呢?對啊,因此下面的案例咱們就用了封裝好的HTTP模塊。
代碼演示:用node搭建HTTP服務器
咱們在代碼中看到'Content-Type',它的做用是規定內容的格式。
問題:如今你把實戰中的狀態碼改爲400,發現頁面仍然能正常訪問。這其實就是你和後端按照標準預約的啊,那麼是有什麼樣子的標準呢?
HTTP狀態碼:是客戶端向服務端發送請求,描述請求的狀態。 狀態碼組成:以3位數字和緣由短語組成 好比(200 OK 和 206 Partial Content)
第一位數字表明類別:
- 1XX : 信息性狀態碼(接收請求正在處理)
- 2XX : 成功狀態碼(請求正常處理完畢)
- 3XX : 重定向狀態碼(須要進行附加操做以完成請求)
- 4XX : 客戶端錯誤狀態碼(服務器沒法處理請求)
- 5XX : 服務端錯誤狀態碼(服務器處理請求出錯)
複製代碼
因此狀態碼就是先後端通訊時對於狀態的一種約定,原則上只要遵循狀態碼類別的定義,即便改變RFC2616定義的狀態碼,或自行建立都是沒問題的。
像上面你非將200成功狀態改爲400,就比如,你把紅燈換成綠燈,老司機們都會亂了套。那如今咱們看看老司機們都經常使用的狀態碼都有哪些吧。
- 200 OK :請求被正常處理返回 200 OK,這也是咱們最多見的啦
- 204 No Content :請求處理成功可是沒有資源返回,就是報文中沒有報文主體
- 206 Partial Content :客戶端進行範圍請求,就是請求資源一部分,服務器返回請求這部分(Content-Range)
- 301 Moved Permanently:永久重定向(資源的URL已經更新)
- 302 Found :臨時重定向(資源的URI已經臨時定位到其餘位置了)
- 303 See Other: 對應的資源存在另外一URL,資源的URL已經更新,是否按新的去訪問
- 304 Not Modified:客戶端發附帶條件的請求,服務端容許請求訪問資源,但沒有知足條件
- 307 Temporary Redirect: 也是臨時重定向
- 400 Bad Request : 請求報文中存在語法錯誤
- 401 Unauthorized : 須要有HTTP認證
- 403 Forbidden : 請求訪問的資源被服務器拒絕了
- 404 Not Found : 服務器上沒有找到資源
- 500 Internal Server Error: 服務器執行請求時出錯
- 503 Service Unavailable : 服務器處於超負載,正在進行停機維護
複製代碼
代碼演示:用url路徑模塊,完成了node路由
(測試題3)單選題 http狀態碼(來自阿里技術之瞳)
chrome DevTools的Network面板中參看靜態資源加載狀況,當發現靜態資源的HTTP狀態碼
是___時,須要使用強制刷新以便得到最新版的靜態資源?
A 204
B 304
C 403
D 501
答案:B
解析:304是資源重定向,客戶端發附帶條件的請求,服務端容許請求訪問資源,但沒有知足條件
你是否是還有點蒙呢,彆着急httpd的緩存協議裏你就會看見它啦。
複製代碼
問題:咱們知道了狀態碼錶明的含義,可是它們在什麼場景下會出現呢?讓咱們一個一個去學習吧
HTTP壓縮協議理解起來很簡單,就好像你要給你朋友在QQ上傳1個1G文件,須要10分鐘,哇網速好快哦。 可是你要是壓縮一下,這個文件就變成了300M。再給你朋友傳可能就須要3分鐘。而後你壓縮須要1分鐘,他解壓須要一分鐘。這樣大家5分鐘就搞定啦。一樣的道理。
這是瀏覽器告訴服務器我支持什麼樣的壓縮格式,優先級是什麼樣的。
這是服務器告訴瀏覽器我已經按什麼樣子的格式壓縮了,解壓工做你拜託你了
因此在瀏覽器上咱們就須要根據請求頭中的Accept-Encoding去判斷,瀏覽器支持什麼壓縮啊。而後壓縮以後再告訴瀏覽器,我已經給你壓縮成什麼樣子啦。
代碼演示:2.5 用gzip對文件進行壓縮
Catche Contrl: :是通用首部字段,就是以前將的發送報文和響應報文都會使用的。能夠對文件裏引用資源的緩存進行設置
這裏舉一個簡單的例子:
瀏覽器發訪問http://localhost:10080/
- '請求報文沒帶 Cache-Control' 客戶端說我要訪問首頁
服務器返回數據
- '響應報文帶:Cache-Control : max-age = 604800' 服務器說給你index.html和加載裏面資源,並告訴你這些資源一週以內不要沒必要確認了
瀏覽器刷新的網頁再次訪問http://localhost:10080/時
- 裏面的資源就不會再發送請求了,直接從緩存中拿 你會在chrome,network中看到Time是0(from memory catch)
服務器返回數據
- 服務器只返回index.html文件
這時候你強制刷新瀏覽器(command+shift+R)
- '請求報文帶 Catche Contrl:no-cache '客戶端說我不要緩存過的數據,我要源服務器的數據
服務器返回數據
- 服務器返回index.html文件和依賴的資源
複製代碼
這就是強緩存,所謂強是在條件內,你網頁依賴的資源都不會發送http請求了。能夠直接從網頁裏面拿。
代碼演示:瀏覽器緩存協議的實現
有兩種:
第一種:If-Modified-Since/Last-Modified
服務器會下發一個Last-Modified最後修改時間。而後瀏覽器會記住這個時間。當瀏覽器第二次請求時會帶上if-modified-since的時間。服務器能夠去比較這份文件在if-modified-since的時間後是否修改過。若是沒有修改過,那就返回304.
代碼演示:瀏覽器緩存協議的實現
上面那個代碼中咱們服務器並無實現去記錄文件修改時間,咱們只要拿一段時間內去比較。咱們知道了使用 if-modified-since,服務器就要每次記錄文件的一個修改時間。因此用時間去判斷並非很好。
第二種:Etag/ If-None-Match
服務器Etag會下發一個字符串,而後瀏覽器在第二次請求時會在if-none-match中帶上這個字符串。這時候服務器能夠比較兩個字符串,若是相同,就讓瀏覽器去緩存中去取。
代碼演示:瀏覽器緩存協議的實現
那麼如今在學完兩種緩存以後,你會問,若是同時都有,那麼瀏覽器是如何判斷的呢?
因此能夠看出,強緩存優先於協商緩存。
(習題4)不定選項 HTTP緩存 (來自京東2018秋招筆試題)
如下哪些是HTTP請求中瀏覽器緩存機制會用到的協議頭?
A Last-Modified
B Etag
C Referer
D Authorization
答案: A B
複製代碼
post和get區別最近好像總有爭論,到底有什麼區別。既然都是應用層的協議,咱們不妨迴歸到本質就看看。咱們先來將一下http都有哪些方法,再說post和get的區別。
協議不久是規定應用層雙方的行爲和約定嗎?那麼咱們就分別從瀏覽器和服務器去看看。
瀏覽器:
服務器:
這裏若是不是理解,建議先把這小節實戰代碼看一下:2.6 瀏覽器緩存協議的實現
看完服務具體是如何響應的,如今你對下面這句話是否是理解了呢?
「GET和POST最大的區別主要是GET請求是冪等性的,POST請求不是。冪等性是指一次和屢次請求某一個資源應該具備一樣的反作用。簡單來講意味着對同一URL的多個請求應該返回一樣的結果。」
答了這麼多,不知道你發現沒有。瀏覽器的全部行爲都是根據這兩個動做作出的相關反應啊。 那麼何時使用get,何時使用post?
根據協議使用啊,不都給你規定好了嗎?請求數據的時候用get,傳輸實體主體的時候用post。
問題:哈哈,學到這,你是否是漸漸明白,並找到一直學很差網絡的緣由了,都怪瀏覽器太智能!對,現代瀏覽器已經很是智能了,因此不少時候,即便的代碼質量不高,它也能給你有很好的優化。可是咱們畢竟仍是要作一名合格的前端工程師,那麼下一節就讓咱們走進瀏覽器吧
對於前端工程師來講,AJAX再熟悉不過了,咱們知道它是用來發送http請求的。那麼它到底與http什麼關係?那咱們先來手寫一個AJAX。
AJAX全稱是Asynchronous JavaScript and XML(異步js和XML)。異步js,咱們比較容易理解。那麼什麼是XHR呢。
XHR全稱是XMLHttpRequest,就是XML的http的請求。其實這是一個瀏覽器層面的API。通俗點講就是瀏覽器給你封裝好了的http功能函數。
在以前的課程,咱們發送的http請求都是瀏覽器本身主動發送的。若是,瀏覽器沒有開放這麼一個功能。你就固然沒有能力主動向服務器獲取數據。因此就完不成交互。這就是爲何在AJAX 以前要經過刷新頁面來解決。
那麼咱們如何理解XHR是瀏覽器層面的API?
咱們在node服務端的時候知道,咱們常常須要須要操做請求頭中的數據,好比根據請求頭中的壓縮機制作出相應的處理。但咱們在前端用ajax獲得數據的時候。並不用考慮壓縮啊,這就是由於XHR是一個瀏覽器層面的API。它向咱們隱藏了大量的底層處理,好比壓縮,緩存。換句話說,瀏覽器也沒有開放給你作這些事能力。
總結一下,其實很好理解,咱們的web頁面是跑在瀏覽器上的,雖然瀏覽器是智能的,但也是通用的,不是爲咱們定製的。這也正是webapp不如原生app的體驗流暢的緣由啊。原聲app能夠理解爲(瀏覽器+頁面)。而webapp是在瀏覽器上寫內容。
可是瀏覽器單單發送http請求的是不能知足咱們平常開發需求的。爲了完成跟多的功能,咱們有長輪詢,瀏覽器也提供的了websocket的API。這寫具體涉及到業務的場景的功能。有機會單寫一篇吧。
問題:咱們知道了瀏覽器給咱們帶來不少的限制,那麼具體業務有哪些影響呢?
因此咱們再XHR的會有不少限制,其中對咱們影響很大的就是不容許發送不一樣協議,地址和端口號的請求。
那麼咱們常見的解決方案有三種:
cors的辦法也很簡單:
固然,爲了安全起見CORS的請求都會忽略掉cookie 和 HTTP認證等用戶憑證。若是你想用,一樣在請求頭帶Origin時在發送一些參數。服務器也是在第一次返回時告訴瀏覽器贊成仍是不一樣意。
代碼演示: 2.8 node處理跨域
因此這節的重點就是http2就解決了隊首阻塞的問題。但http2是基於https的,那就讓咱們先學習https吧
HTTPS是針對HTTP安全性不足,作的改進,咱們先看看HTTP安全性都有哪些不足
** 因此 HTTS = HTTP + 加密 + 認證 + 完整性保護 **
那麼如今咱們先看看如何加密解密的吧?
好比我有一份數據要給你,我只須要把它加密了,你在解密這樣不就安全了。
因此我有一個私鑰用來加密,給別人解密的是公鑰
可是這個時候,咱們又不能保證別人拿到的公鑰就是個人公鑰。萬一數據沒有變,可是公鑰被劫持,解密出來的內容就也不是我想發給對方的啦
因此我把公鑰交給第三方CA認證一下,第三方把公鑰變成了證書
這樣瀏覽器再拿到我發給它的證書的時候,他去和第三方CA問一下,這是否是他的證書啊。
第三方說是,這樣咱們就安全了。
一樣瀏覽器也會以一樣的私鑰和證書的方式對傳給服務器的數據進行加密解密。在第三方認證的時候,咱們會詳細登記本身的信息。這樣咱們彼此也就完成了身份認證。
最後,這個加密算法還用摘要功能來保證數據的完整性
如今咱們知道了就是經過一個私鑰和證書對數據進行進行加解密。因此HTTPS協議只是HTTP通訊接口部分用SSL協議代替而已。而剛纔咱們講的這個過程就是SSL協議的內容。它是由網景公司發明,後來轉交給IETF,IETF在SSL基礎上制定的TLS(改個名字)。
代碼演示:3.1 https的node服務器的搭建
如今終於來到咱們http2啦。還記得咱們說的http1.1的對手阻塞嘛。對http2就解決了這個問題。
那麼如今有一個問題,http2中,既然沒有先進先出,那麼重要的文件加載的慢,那不就尷尬啦。
咱們可讓一些重要的請求優先加載。瀏覽器也智能的根據http2定義出的優先級規則去顯示頁面。
咱們知道咱們在用Gzip方式給報文體進行壓縮。http2給報文頭也進行了壓縮。你可別小看了報文頭,通常網頁的報文頭能佔到報文的40%。 而壓縮後能減小60%左右。
接下來就讓咱們動手去實踐一下吧。
最後,寫的好累。。。以爲這一篇寫不完。後邊寫的太糙了。我慢慢改改。拓展有空在寫吧。