前端計算機網絡基礎
整理這篇文章需要30分鐘:
一站到底 ---前端基礎之網絡
網絡相關的知識是每個前端工程師都應該具備的。很多從事前端的朋友們都沒系統學習過計算機網絡和http相關內容。在沒有建立一個整體的知識體系下,會有一種一站到底答題的感覺,每個知識點都大致知道問題的答案,但總不確定,更不知道具體是怎麽回事。本文系統的梳理了與前端密切相關的網絡知識。(這是我自己學習的總結,整理出的筆記,分享給大家) 還是老規則,在學之前,我們先考考自己,我整理一下知識點,看看我們需要掌握那些問題。然後我們通過把問題知識點串起來去總結。必會:
- http報文都有哪些內容?
- HTTP協議頭含有哪些重要的部分,HTTP狀態碼?
- HTTP狀態碼狀態碼都有哪些?
- 什麽是強緩存?什麽是弱緩存?
- 瀏覽器的現緩存機制是什麽?如何設置HTTP緩存?
- 你知道有哪些HTTP方法?POST 和 PUT 有什麽區別?
- 如何對數據進行壓縮(ZLIB),Gzip? 壓縮的範圍是什麽,請求頭會壓縮嗎?
- 跨域,為什麽JS會對跨域做出限制?如何允許跨域?
基礎:
- 影響網速的原因有哪些?網絡丟包的主要原因是什麽?
- 網絡體系結構的五層參考模型都是什麽?它們之間的關系是什麽?
- 我們常聽到報文、段(分組)、數據報、幀、和數據包,它們有什麽關系?
- Ajax能發送http請求,它和http有什麽樣的關系?
- HTTP1.0 到 http1.1 解決了什麽問題?
- http2有什麽特性?
- http1.1為什麽會有隊首阻塞?
- SSL與TLS關系?HTTPS協議如何實現?
補課與拓展:(慢慢更新)
- 常用的傳輸層協議有哪些?TCP和UDP分別有什麽特點?
- 解釋一下TCP的三次握手和四次揮手?
- 為什麽說TCP可能是網絡通信的瓶頸?如何解決TCP隊首阻塞?
- 谷歌新出QUIC為什麽要基於UDP?
- QUIC有哪些新特性,解決了什麽問題?
必會是和前端工作中聯系最緊密的http協議相關的內容。但是如果沒有網絡基礎,就好像空中樓閣。無法建立起知識體系。所以本文會把必會和基礎放到一起,也就是本文的1-5章內容。
補課與擴展:而深入學習下一代QUIC就必須了解TCP和UDP的具體工作原理。所以這裏會給大家偷偷補課。一些常用的拓展內容也會放到後邊幾章。
本文會用node做代碼演示,相關代碼在github上。如果node基礎不好的同學,我把本章所有的代碼整理成了一篇node的學習文檔。《node.js的小美好》 。每一小節會有一些習題,用來鞏固復習,我慢慢加。
1 網絡基礎
我們從第一題開始,當瀏覽器訪問www.jd.com時,我們都知道瀏覽器向服務器發送了http請求,會把請求報文發送給服務器。那麽我先粗略分析一下這個過程。
1.1 分組傳遞
瀏覽器會基於http協議產生一個http報文(消息),然後會把這個報文拆分成不同的分組(包)。發送到路由上。路由先進行緩存,然後在根據路由表轉發給下一個路由,直到到達服務器。
客戶端 ---> 路由--->路由.......----> 路由--->服務器
我們為什麽不直接把消息發送給服務器,為什麽一定要分包呢?
首先,路由是先緩存再轉發,如果把整個報文直接發給服務器,那麽對路由內存要求會非常高。另外還有一個重要的概念就是網絡的帶寬,也是在鏈路上的傳輸速率,它是由單位時間內可以傳輸的數據總量決定的。而不是我們物理距離,舉個例子。
(1)基礎題 (來自《阿裏技術之瞳》)
使用一輛卡車運輸n塊裝滿數據的1TB硬盤,以80km/h速度行駛1000km將數據運送到目的地,
卡車至少運送多少塊硬盤才能使傳輸速率超過1000Gbit/s?
答案:5625
解析:這個問題可以簡化成兩種方案在相同時間內兩種方案要傳輸相同的數據量。
卡車的時間為: 1000km ÷ 80Km = 12.5h
在相同時間內網絡傳輸的數據量為: 12.5h * 3600s/h * 1000Gbit/s ÷ 8b/B = 562000GB.
那麽卡車需要運輸相同的運算量,562000GB ÷ 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個已經到達h2服務器
當第5000個到達A時,第4999個到底B,其余都到達。這時候用時5s
當第5000個到達h2時,就用時,5秒零2毫秒。
最後總結一下:
- 報文:M bits
- 鏈路寬帶:R bps
- 路由器數:n
- 分組長度:L bits
- 一次報文交換交付時間 : T = n(M / R)
- 分組交換報文交付時間:T = M / R + nL/R
所以可以看出分組交換比一次報文交互性能要好。而上面所用的時間就叫作傳輸延遲
傳輸延遲是影響網速的最主要原因,那麽還有一些影響網速的原因我們來看看:
- 排隊延時:比如當第1個到包達時A時,如果它前面已經有一些其他客戶端的包到達,那麽它就許多排隊等待。排隊所用的時間就是排隊延時。
- 結點處理延遲:排隊到了以後,結點A會對包進行一些處理,這個處理時間叫結點處理延遲,通常是毫秒級的影響非常小。
- 傳播延遲: A出發後,從A到B在鏈路上傳播還要經過一定物理距離,但傳輸的速度非常快,通常是0.7倍的光速,所用的時間叫傳播延遲。
- 丟包: 如果很多客戶端同時向A結點發送數據包,A的緩存滿了以後,對接下來的數據包,會丟棄。而這正是丟包的主要原因。
問題:現在我們粗略了解了這個過程,那麽具體都經歷那些過程呢?
1.2 網絡體系結構
我們先看來看OSI解釋的七成參考模型。
- 分層:我們根據不同的功能把網絡模型分層。
- 協議:不同層之間規定了不同協議,每個層遵循每個層的網絡協議完成完成功能。
- 接口:層與層之間會通過接口去進行交互。
所以這也符合我們函數的模塊化,低層函數定義好接口API,你按照函數的接口文檔去調用依賴的函數,然後就等著讓它去處理。在實際的開發中,我們就是這麽去實現的。
每一層通過本層的協議,增加控制信息,構造協議數據單元PUD。
應用層:
- 瀏覽器根據http協議,產生報文頭和主體
- 對並報文進行編碼,加密,壓縮。
- 將數據封裝好後,交給下一層,我們將這一層的PUD叫 報文(message)
傳輸層:
- 在瀏覽器端會將報文分組,在服務器端會將報文重組。
- 在每個分組的頭,會加上自己協議信息。
- 這些協議信息主要功能是SAP尋址,連接控制,流量控制,差錯控制
- 將數據封裝好後,交給下一層,我們將這一層的PUD叫 段(segment)
網絡層:
- 網絡層在拿個每個段後,會根據IP協議,加上自己協議信息
- 這些協議信息主要功能是:邏輯尋址(IP地址)路由轉發。
- 將數據封裝好後,交給下一層,我們將這一層的PUD叫 數據報(datagram)
鏈路層:
- 網絡層在拿個每個段後,會根據IP協議,加上自己協議信息
- 這些協議信息主要功能是:物理尋址(MAC地址),流量控制,差錯控制,接入控制。
- 將數據封裝好後,交給下一層,我們將這一層的PUD叫 幀(frame)
物理層:
- 物理層在拿個幀後,會把它轉化成 比特(bit),就是位,二進制編碼(一堆100111)
- 然後將這些二進制,根據自己物理特性去表示,比如電信號啥的。
- 然後就把它交給物理介質去傳輸啦
所以現在我們知道了,每發送一個http請求,是針對應用層的請求和響應。應用層雖然來回只有一次。但它下面傳輸層,要把整個報文,分成許多分組,再交給下一層,著名的TCP三次鏈接就是指的傳輸層的。所以應用層的一次請求和響應,再鏈路是可能要走許多次。每個包肯定是肯定擁有每個層的協議,不可能只有上層沒有下層。而我們常說的數據包,就應該是一個段(分組)經過處理成,最後變成比特在鏈路上傳輸。
你會發現我們並沒有講表示層和會話層?因為
應用層 和 傳輸層 我們後邊都會詳細講。這裏我們再講一下 網絡層,鏈路層,物理層。
1.3 鏈路層與物理層
上面我們知道,物理層會把比特在物理介質上傳輸。那麽主機可能和多臺電腦相連,那麽二進制碼怎麽會知道 這是發個那臺電腦,走那條網線呢?
我們知道在鏈路層會加上要訪問主機的物理尋址(MAC地址),所以如果網線連多個電腦,會送到每臺電腦,在物理層轉化回幀,發現如果不是目標電腦的Mac地址,就不去處理。直到找到目標Mac地址的電腦。這裏用到的就是MAC協議。
1.4 網絡層與鏈路層
那麽鏈路層是怎麽知道目標機器的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的時候,我們用不到。
2 應用層
2.1 應用層協議
應用層是基於傳輸層協議之上。常見的傳輸層協議有TCP,UDP。
- 基於TCP:HTTP(超文本傳輸協議),FTP(文件傳輸協議),SMTP(郵件傳輸協議)
- 基於UDP:DNS(域名系統)和最近興起的QUIC(谷歌制定低時延的互聯網傳輸層協議)
應用層的功能是完成客戶端和服務器消息交換。要想完成信息交換就必須知道資源的位置,那我們是怎麽約定資源位置的呢。
2.2 URL:統一資源定位符
語法為:
協議://用戶名:密碼@子域名.域名.頂級域名:端口號/目錄/文件名.文件後綴?參數=值#標誌
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的進行預處理
- decode解碼成普通字符串
- encode普通字符串編碼,編碼後的名字非常長叫(application/x-www-form-urlencoded MIME 字符串)
2.3 代碼演示
應用層的功能是完成客戶端和服務器消息交換。
- 瀏覽器發送http請求:會輸入ip服務和端口
- 服務器監聽端口號,在收到請求時作出響應的
代碼演示1 node創建TCP服務器
這時我們會過頭來看,瀏覽器左下角,是不是一直在顯示等待響應,是因為我們還沒有返回數據啊,那我們給 它返回一些數據。
代碼演示1 node創建TCP服務器
這裏我們先不用管TCP的細節部分,我們會在傳輸層部分去講。
問題:在大致了解了應用層協議後,就讓我們去具體學習http協議吧
3 HTTP協議:
這一節的內容,可是前端的看家本領,大家一定要對應著代碼自己敲出來,看看效果
- HTTP是超文本傳輸協議,從www瀏覽器傳輸到本地瀏覽器的 一種傳輸協議,
- HTTP協議是由從客戶機到服務器的請求(Request)和從服務器 到客戶機的響應(response)進行約束和規範。
3.1 HTTP報文
HTTP報文:用於HTTP協議交互的信息被稱為HTTP報文。
- 請求(Request)端的報文叫請求報文
- 響應(response)端的報文叫響應報文
我們那上一節以響應報文為例,我們之前說要符合http協議的規則,那麽http規則是什麽呢?
let responseDataTpl = `HTTP/1.1 200 OK
Connection:keep-alive
Date: ${new Date()}
Content-Length: 12
Content-Type: text/plain
Hello world!
`;
- 報文首部和報文主體中間要有空行(CR+LF:回車+換行)
- 報文首部:處理請求和響應提供的信息(上文中設置的各種信息)
- 報文主體:所需要的資源都在(比如返回的文本信息就是Hello world)
報文首部:根據實際用途會分為四種
- 通用首部字段(General):請求報文和響應報文都會使用的字段
- 請求首部字段(Requse Header):請求報文使用的首部
- 響應首部字段(Response Header):響應報文使用的首部
- 實體首部字段(Entity Header):與實體有關信息的字段
所以在chrome的network中,header會顯示為:
- General
- Response Headers
- Requse Headers
實體首部字段會寫進請求頭和響應頭 對於get請求後邊的參數會顯示在Query String Parameters
在上邊TCP服務器中,我們發現每次寫符合http協議格式的響應報文非常麻煩,為什麽我們不封裝好呢?對啊,所以下面的案例我們就用了封裝好的HTTP模塊。
代碼演示:用node搭建HTTP服務器
我們在代碼中看到‘Content-Type‘,它的作用是規定內容的格式。
問題:現在你把實戰中的狀態碼改成400,發現頁面仍然能正常訪問。這其實就是你和後端按照標準預定的啊,那麽是有什麽樣子的標準呢?
3.2 HTTP狀態碼
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的緩存協議裏你就會看見它啦。
問題:我們知道了狀態碼代表的含義,但是它們在什麽場景下會出現呢?讓我們一個一個去學習吧
3.2 HTTP壓縮協議
HTTP壓縮協議理解起來很簡單,就好像你要給你朋友在QQ上傳1個1G文件,需要10分鐘,哇網速好快哦。 但是你要是壓縮一下,這個文件就變成了300M。再給你朋友傳可能就需要3分鐘。然後你壓縮需要1分鐘,他解壓需要一分鐘。這樣你們5分鐘就搞定啦。同樣的道理。
- http請求頭帶:Accept-Encoding: gzip, deflate, br
這是瀏覽器告訴服務器我支持什麽樣的壓縮格式,優先級是什麽樣的。
- http響應頭帶:Content-Encoding: gzip
這是服務器告訴瀏覽器我已經按什麽樣子的格式壓縮了,解壓工作你拜托你了
所以在瀏覽器上我們就需要根據請求頭中的Accept-Encoding去判斷,瀏覽器支持什麽壓縮啊。然後壓縮之後再告訴瀏覽器,我已經給你壓縮成什麽樣子啦。
代碼演示:2.5 用gzip對文件進行壓縮
3.3 HTTP緩存協議
3.3.1 強緩存
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請求了。可以直接從網頁裏面拿。
代碼演示:瀏覽器緩存協議的實現
3.3.2 協商緩存
有兩種:
第一種:If-Modified-Since/Last-Modified
服務器會下發一個Last-Modified最後修改時間。然後瀏覽器會記住這個時間。當瀏覽器第二次請求時會帶上if-modified-since的時間。服務器可以去比較這份文件在if-modified-since的時間後是否修改過。如果沒有修改過,那就返回304.
- Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
- If-Modified-Since:當資源過期時(使用Cache-Control標識的max-age),發現資源具有Last-Modified聲明,則再次向web服務器請求時帶上頭 If- -Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified- Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說 明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包 體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
代碼演示:瀏覽器緩存協議的實現
上面那個代碼中我們服務器並沒有實現去記錄文件修改時間,我們只要拿一段時間內去比較。我們知道了使用 if-modified-since,服務器就要每次記錄文件的一個修改時間。所以用時間去判斷並不是很好。
第二種:Etag/ If-None-Match
服務器Etag會下發一個字符串,然後瀏覽器在第二次請求時會在if-none-match中帶上這個字符串。這時候服務器可以比較兩個字符串,如果相同,就讓瀏覽器去緩存中去取。
- Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器 的唯一標識(生成規則由服務器決定)
- If-None-Match:當資源過期時(使用Cache-Control標識的max- age),發現資源具有Etage聲明,則再次向web服務器請求時帶 上頭If-None-Match (Etag的值)。web服務器收到請求後發現 有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決 定返回200或304。
代碼演示:瀏覽器緩存協議的實現
那麽現在在學完兩種緩存之後,你會問,如果同時都有,那麽瀏覽器是如何判斷的呢?
3.3.2 協商緩存
有兩種:
第一種:If-Modified-Since/Last-Modified
服務器會下發一個Last-Modified最後修改時間。然後瀏覽器會記住這個時間。當瀏覽器第二次請求時會帶上if-modified-since的時間。服務器可以去比較這份文件在if-modified-since的時間後是否修改過。如果沒有修改過,那就返回304.
- Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
- If-Modified-Since:當資源過期時(使用Cache-Control標識的max-age),發現資源具有Last-Modified聲明,則再次向web服務器請求時帶上頭 If- -Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified- Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說 明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包 體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
代碼演示:瀏覽器緩存協議的實現
上面那個代碼中我們服務器並沒有實現去記錄文件修改時間,我們只要拿一段時間內去比較。我們知道了使用 if-modified-since,服務器就要每次記錄文件的一個修改時間。所以用時間去判斷並不是很好。
第二種:Etag/ If-None-Match
服務器Etag會下發一個字符串,然後瀏覽器在第二次請求時會在if-none-match中帶上這個字符串。這時候服務器可以比較兩個字符串,如果相同,就讓瀏覽器去緩存中去取。
- Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器 的唯一標識(生成規則由服務器決定)
- If-None-Match:當資源過期時(使用Cache-Control標識的max- age),發現資源具有Etage聲明,則再次向web服務器請求時帶 上頭If-None-Match (Etag的值)。web服務器收到請求後發現 有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決 定返回200或304。
代碼演示:瀏覽器緩存協議的實現
那麽現在在學完兩種緩存之後,你會問,如果同時都有,那麽瀏覽器是如何判斷的呢?
所以可以看出,強緩存優先於協商緩存。
(習題4)不定選項 HTTP緩存 (來自京東2018秋招筆試題)
以下哪些是HTTP請求中瀏覽器緩存機制會用到的協議頭?
A Last-Modified
B Etag
C Referer
D Authorization
答案: A B
3.4 HTTP方法
post和get區別最近好像總有爭論,到底有什麽區別。既然都是應用層的協議,我們不妨回歸到本質就看看。我們先來將一下http都有哪些方法,再說post和get的區別。
3.4.1 HTTP方法
- GET:獲取資源
- POST:傳輸實體主體
- PUT:傳輸文件
- HEAD:獲取報文首部
- DELETE:刪除文件
- OPTIONS:查詢支持方法
- TRACK:追蹤路徑
- CONNECT:要求用隧道協議連接代理
3.4.2 GET 與 POST區別
協議不久是規定應用層雙方的行為和約定嗎?那麽我們就分別從瀏覽器和服務器去看看。
瀏覽器:
- GET是請求數據,使用URL或Cookie傳參。POST是傳輸實體主體所以會把參數放到報文體中
- GET數據放到URL中,瀏覽器對URL大小有限制,所以數據大小進行限制。POST是傳輸實體主體,所以大小沒有限制
- GET數據放到URL中,所以安全性肯定不高啊,所以不能用來傳遞敏感信息。POST相對安全
- GET是請求數據所以URL地址可以後退,而POST發送數據不會(chrome中post就會後退)。
- GET是請求所以會被瀏覽器主動cache,而POST是發送數據,所以不會除非手動設置。
服務器:
- get是把參數放到URL中去處理
- 而post是觸發了服務器中監聽的請求事件,服務器可能會做出處理,影響返回結果
這裏如果不是理解,建議先把這小節實戰代碼看一下:2.6 瀏覽器緩存協議的實現
看完服務具體是如何響應的,現在你對下面這句話是不是理解了呢?
“GET和POST最大的區別主要是GET請求是冪等性的,POST請求不是。冪等性是指一次和多次請求某一個資源應該具有同樣的副作用。簡單來說意味著對同一URL的多個請求應該返回同樣的結果。”
答了這麽多,不知道你發現沒有。瀏覽器的所有行為都是根據這兩個動作做出的相關反應啊。 那麽什麽時候使用get,什麽時候使用post?
根據協議使用啊,不都給你規定好了嗎?請求數據的時候用get,傳輸實體主體的時候用post。
問題:哈哈,學到這,你是不是漸漸明白,並找到一直學不好網絡的原因了,都怪瀏覽器太智能!對,現代瀏覽器已經非常智能了,所以很多時候,即使的代碼質量不高,它也能給你有很好的優化。但是我們畢竟還是要做一名合格的前端工程師,那麽下一節就讓我們走進瀏覽器吧
4 瀏覽器與協議
4.1 XHR 與 AJAX
對於前端工程師來說,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。這寫具體涉及到業務的場景的功能。有機會單寫一篇吧。
問題:我們知道了瀏覽器給我們帶來很多的限制,那麽具體業務有哪些影響呢?
5 http發展
5.1 HTTP1.0 到http1.1
- HTTP1.0的時候,每次發送一個http請求就要建立一次TCP連接,然後再斷開
- http1.1的時候,引入了Connection:keep-alive的機制,連接後不斷開可以繼續發送請求
- 但每次請求都是第一個回來,第二個再出發。後來瀏覽器又引入了 pipelining的管道化連接。
- 在一個TCP連接內,多個HTTP請求可以並行,下一個HTTP請求在上一個HTTP請求的應答完成之前就發起 這個不需要你去設置,引入了Connection:keep-alive,瀏覽器自動會這麽處理。但這又有一個問題,由於HTTP1.1服務端返回響應數據的順序必須跟客戶端請求時的順序一致,這樣也就是要求先進先出。所以很容易造成隊首阻塞。就是你第一個請求不返回,後面都得在那等著。
所以這節的重點就是http2就解決了隊首阻塞的問題。但http2是基於https的,那就讓我們先學習https吧
5.2 HTTPS
HTTPS是針對HTTP安全性不足,做的改進,我們先看看HTTP安全性都有哪些不足
- 通信就是明文
- 沒有驗證通信方身份
- 無法證明報文完整性
** 所以 HTTS = HTTP + 加密 + 認證 + 完整性保護 **
那麽現在我們先看看如何加密解密的吧?
-
比如我有一份數據要給你,我只需要把它加密了,你在解密這樣不就安全了。
-
所以我有一個私鑰用來加密,給別人解密的是公鑰
-
但是這個時候,我們又不能保證別人拿到的公鑰就是我的公鑰。萬一數據沒有變,但是公鑰被劫持,解密出來的內容就也不是我想發給對方的啦
-
所以我把公鑰交給第三方CA認證一下,第三方把公鑰變成了證書
-
這樣瀏覽器再拿到我發給它的證書的時候,他去和第三方CA問一下,這是不是他的證書啊。
-
第三方說是,這樣我們就安全了。
-
同樣瀏覽器也會以同樣的私鑰和證書的方式對傳給服務器的數據進行加密解密。在第三方認證的時候,我們會詳細登記自己的信息。這樣我們彼此也就完成了身份認證。
-
最後,這個加密算法還用摘要功能來保證數據的完整性
現在我們知道了就是通過一個私鑰和證書對數據進行進行加解密。所以HTTPS協議只是HTTP通信接口部分用SSL協議代替而已。而剛才我們講的這個過程就是SSL協議的內容。它是由網景公司發明,後來轉交給IETF,IETF在SSL基礎上制定的TLS(改個名字)。
代碼演示:3.1 https的node服務器的搭建
5.2 HTTP2.0
現在終於來到我們http2啦。還記得我們說的http1.1的對手阻塞嘛。對http2就解決了這個問題。
- (1)多路復用,並不在遵循先進先出。
那麽現在有一個問題,http2中,既然沒有先進先出,那麽重要的文件加載的慢,那不就尷尬啦。
- (2)http2定義了請求優先級
我們可以讓一些重要的請求優先加載。瀏覽器也智能的根據http2定義出的優先級規則去顯示頁面。
- (3)頭部壓縮
我們知道我們在用Gzip方式給報文體進行壓縮。http2給報文頭也進行了壓縮。你可別小看了報文頭,一般網頁的報文頭能占到報文的40%。 而壓縮後能減少60%左右。
- (4)性能上新增了二進制分幀層。也得到了大大的提升。分針層對應的就是http報文。所以http/1.1是一個文本協議,而 http2 是一個徹徹底底的二進制協議。
接下來就讓我們動手去實踐一下吧。
最後,寫的好累。。。覺得這一篇寫不完。後邊寫的太糙了。我慢慢改改。拓展有空在寫吧。
前端計算機網絡基礎