自從入職新公司到現在,我們前端團隊內部一直在做 ??每週一練 的知識複習計劃,我之前整理了一個 每週一練 之 數據結構與演算法 學習內容,大家也快去看看~~
最近三週,主要複習 網路基礎 相關的知識,今天我把這三週複習的知識和參考答案,整理成本文,歡迎各位朋友互相學習和指點,覺得本文不錯,也歡迎點贊哈????。
特別喜歡現在的每週學習和分享,哈哈哈~~??
??推薦一個 github 倉庫 —— 《awesome-http》,內容挺棒的。
註:本文整理資料來源網路,有些圖片/段落找不到原文出處,如有侵權,聯繫刪除。
參考文章:《TCP三次握手和四次揮手協議》
建立 TCP 需要三次握手才能建立,而斷開連接則需要四次握手。整個過程如下圖所示:
TCP三次握手:
所謂的三次握手,是指建立一個 TCP 連接時,需要客戶端和伺服器端總共發送三個包,三次握手的目的是連接伺服器的指定埠,建立 TCP 連接,並同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息,在 SOCKET 編程中,客戶端執行 connect() 時,將會觸發三次握手:
TCP四次揮手:
TCP連接的拆除需要發送四個包,客戶端或者伺服器端均可主動發起揮手動作,在SOCKET編程中,任何一方執行close()即可產生揮手操作。
狀態碼是由 3 位數組成,第一個數字定義了響應的類別,且有五種可能取值:
1xx:指示信息–表示請求已接收,繼續處理。
2xx:成功–表示請求已被成功接收、理解、接受。
3xx:重定向–要完成請求必須進行更進一步的操作。
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。
5xx:伺服器端錯誤–伺服器未能實現合法的請求。
更多完整內容,可以查看 《HTTP響應頭和請求頭信息對照表》
參考文章:《HTTP常用頭部信息》
舉例:
參考文章:《HTTP請求方法對照表》
根據 HTTP 標準,HTTP 請求可以使用多種請求方法。 HTTP1.0 定義了三種請求方法: GET, POST 和 HEAD方法。 HTTP/1.1 新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
參考文章: 《3分鐘搞懂Cookie與Session》
Cookie是存儲在用戶本地計算機上,用於保存一些用戶操作的歷史信息,當用戶再次訪問我們的伺服器的時候,瀏覽器通過HTTP協議,將他們本地的Cookie內容也發到咱們伺服器上,從而完成驗證。
Cookie
Session 存儲在我們的伺服器上,就是在我們的伺服器上保存用戶的操作信息。
當用戶訪問我們的網站時,我們的伺服器會成一個 Session ID,然後把 Session ID 存儲起來,再把這個 Session ID發給我們的用戶,用戶再次訪問我們的伺服器的時候,拿著這個 Session ID就能驗證了,當這個ID能與我們伺服器上存儲的ID對應起來時,我們就可以認為是自己人。
Session ID
Session ID就
seesion
session_id
cookie
PHPSESSIONID
Session
ID
$_SESSION
||Cookie|session| |---|---|---| |定義|瀏覽器保存用戶信息的文件,存儲的數量和字元數都有限制|伺服器把sessionID 和用戶信息、用戶操作,記錄在伺服器上,這些記錄就稱為session | |相同點|都是為了存儲用戶相關的信息| |存儲|客戶端|伺服器| |安全性|安全性不高,任何人都能直接查看|安全性高|
sessionID
session
server side session
client side session
請求報文由請求行、請求頭部和請求正文組成:
格式為:
請求方法 + 空格 + URL + 空格 + 協議版本 + 回車符 + 換行符
例如:
GET www.baidu.com HTTP/1.1
常見的請求方法有:GET,HEAD,PUT,POST,TRACE,OPTIONS,DELETE以及擴展方法。
頭部欄位名 + 冒號(:) + 值 + 回車符 + 換行符
請求頭部為請求報文添加了一些附加信息,由「名/值」對組成,每行一對,名和值之間使用冒號分隔。
並且,在請求頭部的最後會有一個空行,表示請求頭部結束,這一行必不可少。
典型的請求頭部有:
|請求頭部|說明| |---|---| |Host|接受請求的伺服器地址,可以是IP:埠號,也可以是域名| |User-Agent|發送請求的應用程序名稱| |Connection|指定與連接相關的屬性,如Connection:Keep-Alive| |Accept-Charset|通知服務端可以發送的編碼格式| |Accept-Encoding|通知服務端可以發送的數據壓縮格式| |Accept-Language|通知服務端可以發送的語言|
一般使用在 POST 方法中, GET 方法不存在請求正文。
POST
GET
Content-Type
Content-Length
響應報文由狀態行、響應頭部和響應正文組成:
協議版本 + 空格 + 狀態碼 + 空格 + 狀態碼描述 + 回車符 + 換行符
狀態碼劃分:
100?199的狀態碼是 HTTP / 1.1 向協議中引入了信息性狀態碼;
常見的狀態碼:
常見響應頭部:
參考文章:《HTTP/1.0 HTTP/1.1 HTTP/2.0 主要特性對比》
對於 HTTP/1.1,不僅繼承了 HTTP1.0簡單的特點,還克服了諸多 HTTP1.0性能上的問題。
HTTP/1.1
HTTP1.0
也就是多個請求和響應可以利用同一個 TCP 連接,而不是每一次請求響應都要新建一個TCP連接,減少了建立和關閉連接的消耗和延遲。
Connection: keep-alive
增加了管道機制,請求可以同時發出,但是響應必須按照請求發出的順序依次返回,性能在一定程度上得到了改善。
在 HTTP/1.1 版本中,可以不必等待數據完全處理完畢再返回,伺服器產生部分數據,那麼就發送部分數據,很明此種方式更加優秀一些,可以節省很多等待時間。
host
使得一個伺服器能夠用來創建多個 Web 站點。
HTTP/1.1 引入了一個 Warning 頭域,增加對錯誤或警告信息的描述,此外,在 HTTP/1.1 中新增了24個狀態響應碼(100,101,203,205,206,301,305… )。
Warning
HTTP/1.1 中在請求消息中引入了 range頭域,它允許只請求資源的某個部分。
range
在響應消息中 Content-Range頭域聲明瞭返回的這部分對象的偏移值和長度。如果伺服器相應地返回了對象所請求範圍的內容,則響應碼為 206(Partial Content),它可以防止 Cache將響應誤以為是完整的一個對象,HTTP/1.1 加入了一個新的狀態碼 100(Continue)。客戶端事先發送一個只帶頭域的請求,如果伺服器因為許可權拒絕了請求,就回送響應碼 401(Unauthorized);如果伺服器接收此請求就回送響應碼 100,客戶端就可以繼續發送帶實體的完整請求了。
Content-Range
206(Partial Content)
Cache
100(Continue)
401(Unauthorized
100
注意,HTTP/1.0 的客戶端不支持 100 響應碼。但可以讓客戶端在請求消息中加入 Expect頭域,並將它的值設置為 100-continue。
Expect
100-continue
此版本的網路延遲問題主要由於隊頭堵塞導致,雖然通過持久性連接得到改善,但是每一個請求的響應依然需要按照順序排隊,如果前面的響應處理較為耗費時間,那麼同樣非常耗費性能。
還有此版本雖然引進了管道機制,但是當前存在諸多問題,且默認處於關閉狀態。
http/1.1 請求會攜帶大量冗餘的頭信息,浪費了很多寬頻資源。
參考文章:《HTTP1.0 HTTP/1.1 HTTP2.0 主要特性對比》
在應用層(HTTP/2.0)和傳輸層(TCP or UDP)之間增加一個二進位分幀層,從而突破 HTTP1.1 的性能限制,改進傳輸性能,實現低延遲和高吞吐量。
可見,雖然 HTTP/2.0 的協議和 HTTP1.x 協議之間的規範完全不同了,但是實際上 HTTP/2.0並 沒有改變 HTTP1.x 的語義。
簡單來說,HTTP/2.0 只是把原來 HTTP1.x 的 header 和 body 部分用 frame 重新封裝了一層而已。
header
body
frame
允許同時通過單一的 HTTP/2 連接發起多重的請求-響應消息,這個強大的功能則是基於「二進位分幀」的特性。
從圖中可見,所有的 HTTP/2.0 通信都在一個 TCP 連接上完成,這個連接可以承載任意數量的雙向數據流。
每個數據流以消息的形式發送,而消息由一或多個幀組成。這些幀可以亂序發送,然後再根據每個幀頭部的流標識符(stream id)重新組裝。
stream id
HTTP1.1 不支持 header 數據的壓縮,HTTP/2.0 使用 HPACK 演算法對 header 的數據進行壓縮,這樣數據體積小了,在網路上傳輸就會更快。高效的壓縮演算法可以很大的壓縮 header ,減少發送包的數量從而降低延遲。
HPACK
在 HTTP/2 中,伺服器可以對客戶端的一個請求發送多個響應,即伺服器可以額外的向客戶端推送資源,而無需客戶端明確的請求。
參考文章:《深入淺出講解HTTPS工作原理》
HTTPS 並非是應用層的一種新協議。只是 HTTP 通信介面部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)協議代替而已。
通常,HTTP 直接和 TCP 通信。當使用 SSL 時,則演變成先和 SSL 通信,再由 SSL 和 TCP 通信了。簡言之,所謂 HTTPS,其實就是身披 SSL 協議這層外殼的 HTTP。
在採用 SSL 後,HTTP 就擁有了 HTTPS 的加密、證書和完整性保護這些功能。也就是說HTTP 加上加密處理和認證以及完整性保護後即是 HTTPS。
HTTPS 協議的主要功能基本都依賴於 TLS/SSL 協議,TLS/SSL 的功能實現主要依賴於三類基本演算法:散列函數 、對稱加密和非對稱加密,其利用非對稱加密實現身份認證和密鑰協商,對稱加密演算法採用協商的密鑰對數據加密,基於散列函數驗證信息的完整性。
HTTPS 其實是有兩部分組成:HTTP + SSL / TLS,也就是在 HTTP 上又加了一層處理加密信息的模塊。服務端和客戶端的信息傳輸都會通過 TLS 進行加密,所以傳輸的數據都是加密後的數據。
瀏覽器裡面輸入一個HTTPS網址,然後連接到服務端的443埠上。注意這個過程中客戶端會發送一個密文族給服務端,密文族是瀏覽器所支持的加密演算法的清單。
採用HTTPS協議的伺服器必須要有一套數字證書,可以自己製作,也可以向組織申請。區別就是自己頒發的證書需要客戶端驗證通過纔可以繼續訪問,而使用受信任的公司申請的證書則不會彈出提示頁面。
這套證書其實就是一對公鑰和私鑰,可以這麼理解,公鑰就是一把鎖頭,私鑰就是這把鎖的鑰匙,鎖頭可以給別人對某個東西進行加鎖,但是加鎖完畢之後,只有持有這把鎖的鑰匙纔可以解鎖看到加鎖的內容。
這個證書其實就是公鑰,只是包含了很多信息,如證書的頒發機構、過期時間等等。
這部分工作是由客戶端的TLS來完成的,首先會驗證公鑰是否有效,如頒發機構、過期時間等等,如果發現異常則會彈出一個警告框,提示證書存在問題。如果證書沒有問題,那麼就生成一個隨機值,然後用證書對該隨機值進行加密。
注意一下上面提到的"發現異常"。證書中會包含數字簽名,該數字簽名是加密過的,是用頒發機構的私鑰對本證書的公鑰、名稱及其他信息做hash散列加密而生成的。客戶端瀏覽器會首先找到該證書的根證書頒發機構,如果有,則用該根證書的公鑰解密伺服器下發的證書,如果不能正常解密,則就是"發現異常",說明該證書是偽造的。
這部分傳送的是用證書加密後的隨機值,目的就是讓服務端得到這個隨機值,然後客戶端和服務端的通信就可以通過這個隨機值來進行加密和解密了。
服務端用私鑰解密後,得到了客戶端傳過來的隨機值,至此一個非對稱加密的過程結束,看到TLS利用非對稱加密實現了身份認證和密鑰協商。然後把內容通過該值進行對稱加密。
這部分是服務端用隨機值加密後的信息,可以在客戶端被還原。
客戶端用之前生成的隨機值解密服務端傳送過來的信息,於是獲取了解密後的內容,至此一個對稱加密的過程結束,看到對稱加密是用於對伺服器待傳送給客戶端的數據進行加密用的。整個過程即使第三方監聽了數據,也束手無策。
參考文章:《前端常見跨域解決方案(全)》
跨域,指的是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript施加的安全限制。
同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到 XSS 、 CSFR 等攻擊。所謂同源是指"協議+域名+埠"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
LocalStorage
IndexDB
DOM
JS
Ajax
所謂的同源是指:域名、協議、埠均為相同。
http://www.a.cn/index.html
http://www.a.cn/server.php
http://www.b.cn/server.php
http://abc.a.cn/index.html
http://def.b.cn/server.php
http://www.a.cn:8080/index.html
https://www.a.cn/index.html
localhost
127.0.0.1
jsonp
document.domain
iframe
window.name
location.hash
postMessage
CORS
withCredentials
WebSocket
node
nginx
具體每一種解決方法,可以參考:《前端常見跨域解決方案(全)》
瀏覽器緩存主要分為強緩存(也稱本地緩存)和協商緩存(也稱弱緩存)。
強緩存是利用 http 頭中的 Expires 和 Cache-Control 兩個欄位來控制的,用來表示資源的緩存時間。
http
Expires
Cache-Control
強緩存中,普通刷新會忽略它,但不會清除它,需要強制刷新。瀏覽器強制刷新,請求會帶上 Cache-Control:no-cache 和 Pragma:no-cache。
Cache-Control:no-cache
Pragma:no-cache
通常,強緩存不會向伺服器發送請求,直接從緩存中讀取資源,在chrome控制檯的network選項中可以看到該請求返回200的狀態碼。分為 from disk cache 和 from memory cache。
from disk cache
from memory cache
有緩存命中和緩存未命中狀態:
協商緩存就是由伺服器來確定緩存資源是否可用,所以客戶端與伺服器端要通過某種標識來進行通信,從而讓伺服器判斷請求資源是否可以緩存訪問。
普通刷新會啟用弱緩存,忽略強緩存。只有在地址欄或收藏夾輸入網址、通過鏈接引用資源等情況下,瀏覽器才會啟用強緩存,這也是為什麼有時候我們更新一張圖片、一個js文件,頁面內容依然是舊的,但是直接瀏覽器訪問那個圖片或文件,看到的內容卻是新的。
這個主要涉及到兩組 header 欄位: Etag 和 If-None-Match、 Last-Modified和 If-Modified-Since。
Etag
If-None-Match
Last-Modified
If-Modified-Since
向伺服器發送請求,伺服器會根據這個請求的request header的一些參數來判斷是否命中協商緩存。
瀏覽器第一次發起請求,本地有緩存情況: 在瀏覽器第一次發起請求時,本地無緩存,向web伺服器發送請求,伺服器起端響應請求,瀏覽器端緩存。過程如下:
在第一次請求時,伺服器會將頁面最後修改時間通過 Last-Modified標識由伺服器發送給客戶端,客戶端記錄修改時間;伺服器還會生成一個Etag,並發送給客戶端。
瀏覽器後續再次進行請求時:
參考文章:《LRU演算法》
LRU(Least recently used,最近最少使用)演算法根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是「如果數據最近被訪問過,那麼將來被訪問的幾率也更高」。
這裡有一張比較卡通的圖片:
最常見的實現是使用一個鏈表保存緩存數據,詳細演算法實現如下:
當存在熱點數據時,LRU的效率很好,但偶發性的、週期性的批量操作會導致LRU命中率急劇下降,緩存污染情況比較嚴重。
實現簡單。
命中時需要遍歷鏈表,找到命中的數據塊索引,然後需要將數據移到頭部。
本文主要複習了 HTTP/HTTPS 的一些基礎知識,還有 HTTP 的其他版本的知識,對於面試也好,知識沉澱也好,這些也是我們作為開發者必須懂的。
作為一名前端開發者,說實話對 HTTP/HTTPS 瞭解還是太少,可能和平常工作內容有關。
本文首發在 pingan8787個人博客,如需轉載請保留個人介紹