知識梳理系列之四——網絡協定TCP/IP、Http/Https
- 網絡分層模型若幹問題
-
- OSI七層模型和TCP/IP四層模型
- TCP/IP的握手與揮手
-
- 三次握手:
- 為什麼要三次握手?
- 四次揮手
- 為什麼要四次揮手?
- HTTP協定與HTTPS協定
- HTTP的Cache、Cookies、Session、Token等機制
-
- Cache
- Cookies、Session、Token
網絡分層模型若幹問題
本文是對基本知識的個人總結,旨在面試遇到時,能邏輯條理清晰。不是全面知識學習文本。
OSI七層模型和TCP/IP四層模型
- OSI七層網絡模型和TCP/IP四層模型圖示
TCP/IP是一組協定族,包含很多協定,常見的比如UDP、HTTP、S-HTTP(HTTPS)、SSL/TLS、FTP、SMTP、POP3、DHCP、SOCKS等等,其中HTTP/FTP/SMTP/POP3/SOCKS等屬于應用層協定。TCP/UDP協定是網絡層協定、IP協定是傳輸層協定。
Socket網絡套接字是一個使用TCP/IP的接口,友善通路和使用這些協定,本身不是協定。
-
其中HTTPS協定就是HTTP + SSL/TLS
SSL是Secure Sockets Layer的縮寫,由Netscap釋出,經IEEE标準化為TLS,目前主流的是TLS 1.1、TLS 1.2版本。
-
TCP與UDP的差別:
a. TCP保證資料在網絡中的正确性、順序性,而UDP不保證;
b. UDP由于不保證上述性質,省去了校驗正确和順序收發,在傳輸上更快速。
TCP/IP的握手與揮手
三次握手:
如下圖所示:
說明:三次握手步驟:
- 用戶端服務端分别打開傳輸控制塊TCB,服務端進入LISTEN狀态,客服端發起請求,并帶資料SYN=1,seq=x(seq是一個序列數,序列數一般是發送資料的長度,握手時序列數都是+1不帶其他資料),發送後用戶端進入SYN_SEND狀态;
- 服務端收到請求,并向用戶端回複資料:ACK=1,SYN=1,ack=x+1,seq=y(表示收到了用戶端的SYN=1,回複确認ACK=1,并且用戶端的序列數+1,自己的資料序列數y),服務端進入SYN_RCVD狀态;
- 用戶端收到服務端的确認,并發送建立連接配接确認資料:ACK=1,ack=y+1,seq=x+1(表示用戶端收到了服務端的确認,并回複伺服器建立連接配接),用戶端進入ESTABLISH,服務端收到用戶端的确認資料後也進入ESTABLISH狀态,此時連接配接建立。
為什麼要三次握手?
可以看到完成第二次握手時,相當于服務端收到了用戶端的請求,并且用戶端也知曉的狀态,為什麼還需要進行第三次握手呢?
答案:主要是為了避免失效請求重複連接配接
一種常見場景:
一次用戶端請求發出後,網絡環境不暢,請求停留在網絡中,用戶端在長時間沒有收到回複,嘗試重新請求,此時網絡暢通,并成功建立連接配接,完成資料交換并關閉連接配接,此時停留在網絡中的上次請求又到達了伺服器。
此時,如果隻有兩次握手将再次建立連接配接,這是不符合預期的!并且造成資源浪費。
那麼是三次握手時,服務端收到失效的請求後,向用戶端發送确認資料,但是用戶端發現自己并沒有請求,于是不做回複,此時,避免了失效請求導緻重複連接配接!!
四次揮手
說明:四次揮手步驟:
- 用戶端發起斷開連接配接請求,FIN=1,seq=u,用戶端進入FIN-WAIT-1狀态;
- 服務端收到此請求後,回複用戶端:ACK=1,ack=u+1,seq=v(此時沒有回複FIN=1,因為服務端有可能有資料還沒有發送完,隻告知用戶端我收到了你的FIN請求,我還有資料沒發完),此時服務端進入CLOSE_WAIT狀态,用戶端進入FIN-WAIT-2狀态;
- 直到服務端把最後的資料全部發送完成,服務端會再次向用戶端發送:FIN=1,ACK=1,ack=u+1,seq=w(表示我最後的資料已經發完了),服務端進入LAST_ACK狀态,等待用戶端收到确認;
- 用戶端收到後,發送ACK=1,ack=w+1,seq=u+1(告知服務端我收到了),并進入TIME_WAIT狀态,服務端收到後就CLOSE了,用戶端在TIME_WAIT逾時後進入CLOSE。
為什麼要四次揮手?
分解成兩個問題:
-
為什麼服務端回複用戶端的FIN請求,有兩次一次ACK,一次FIN/ACK?
因為服務端收到請求後,有可能還有用戶端請求的資料沒有發送完成,是以第一次ACK是告知用戶端我收到你的FIN請求了,第二次FIN/ACK是告知用戶端你要的資料我都發出去了。服務端等用戶端确認知曉其已經發送完了資料,如果期間逾時沒有收到确認,服務端還會重發。
-
為什麼用戶端CLOSE之前有TIME_WAIT?
因為用戶端在收到FIN/ACK後需要給服務端ACK,告知我收到了,如果用戶端發完ACK,立即CLOSE,有可能服務端未收到ACK而關閉不了,TIME_WAIT保持用戶端未關閉,是的服務端沒有收到用戶端的ACK時還可以再重發FIN/ACK;
另外一個作用是清除網絡中的無效封包。
HTTP協定與HTTPS協定
HTTP是一種超文本傳輸協定,通常使用統一資源定位符URL來擷取網絡資源。
-
請求封包格式
請求頭: 請求方法(如GET/POST) 資源路徑或參數 HTTP協定版本
請求行: 就是Request對象裡的一系列配置
比如:Host、User-Agent、Content-Type、Content-Length、Content-Encoding、
Content-Language、Accept-Type、Accept-Language、Connection(Keep-Alive)等等;
空行
請求體:(POST有/GET無)
-
響應封包格式
狀态行: 協定版本 狀态碼 狀态短語
響應頭: Date 時間日期
charset 、Content-Type
Content-Length等等
空行
響應正文:比如 json 字元串等
狀态碼:
狀态碼 含義 1xx 繼續執行 2xx 成功 3xx 重定向 4xx 用戶端錯誤 5xx 服務端問題 -
與Https的差別
差別在于在表示層使用了SSL/TLS,來進行身份校驗(伺服器CA憑證),并使用密文傳輸請求資料。
http使用的是明文傳輸。
https會犧牲一部分速度,但總體影響不大;
常用的加密方式非對稱加密、對稱加密;
-
附:有趣的加密原理(Diffie-Hellman算法)
非對稱加密的離散對數方案:
已知公鑰: 質 數 p 、 α 質數p、\alpha 質數p、α
ALICE要和BOB加密通信,不希望被EVE竊密;
希望有一種加密方式,用已知的加密算法,ALICE用私鑰a加密資料Data發送給BOB,BOB接收到密文用自己的私鑰b就能解密;
EVE隻能從網絡中拿到兩者加密後的資料,在一定時間内無法窮舉出密碼。
ALICE: 将計算: y = α a ( m o d p ) y = \alpha^a \ (mod \quad p) y=αa (modp) 将計算結果發送到網絡中;BOB和EVE都可以收到
BOB:将計算: z = α b ( m o d p ) z = \alpha^b \ (mod \quad p) z=αb (modp) 将計算結果發送到網絡中;ALICE和EVE都可以收到
ALICE:将收到的z 進行計算: p r e M a s t e r K e y = z a ( m o d p ) preMasterKey = z^a\ (mod \quad p) preMasterKey=za (modp)
BOB:将收到的y 進行計算: p r e M a s t e r K e y = y b ( m o d p ) preMasterKey = y^b\ (mod \quad p) preMasterKey=yb (modp)
此時發現ALICE和BOB算出了一緻的結果preMasterKey ,這樣就完成了加密通信的建立,確定兩個身份合法的人連接配接到了一起,而EVE由于算不出一緻的結果而無法竊密。
其中mod就是取餘計算。
HTTP的Cache、Cookies、Session、Token等機制
-
由于HTTP是無狀态協定,是以每次建立連接配接之間沒有聯系,如果遇到上一次的資料對下一個請求行為的結果有影響的情況,HTTP協定在協定層面是不好解決的,也不希望破壞無狀态的特性。
于是就出現了Cookies、Session、Token等機制。
- 而Cache機制主要是為了降低伺服器的負載,在一些場景下直接使用緩存而不是直接請求的方式節約資源、提高響應速度。
Cache
-
在響應封包的響應頭中有一個參數:Cache-control: 字段。
這個字段就是設定緩存政策的。
常見的緩存政策有:
緩存政策名 | 含義或用途 |
---|---|
no-store | 不儲存任何緩存,每次都重新請求伺服器擷取資料,相當于沒有緩存。 |
no-cache | 儲存緩存,但是每次都先請求伺服器确認資料是否發生了變化。 1. 若資料未變化,伺服器傳回304,使用緩存資料; 2. 若資料變化,伺服器傳回新的資料供用戶端使用,用戶端更新緩存。 |
max-age | 将設定一個最大新鮮時間。若未逾時,直接使用緩存;若逾時,向伺服器請求資料。 |
private | 預設的配置,隻允許單個用戶端緩存 |
public | 允許網絡代理和用戶端緩存 |
s-maxage | 表示public的緩存的最大新鮮時間 |
max-stale | 表示緩存過期後仍然可用的最大時間 |
min-fresh | 表示響應擷取到後,緩存的最少新鮮時間,min-fresh不能大于max-age,否則失效導緻min-fresh=max-age |
must-revalidate | 在使用緩存之前必須驗證資源是否新鮮 |
一般,public和s-maxage組合使用;
no-cache的優先級更高,no-cache相當于max-age=0 + must-revalidate;
must-revalidate的優先級比max-age更高;
如果沒有no-cache或must-revalidate才執行下面的步驟:
a. 緩存目前的時間age+min-fresh <= max-age 時,認為緩存新鮮可用;
b. age+min-fresh > max-age && age+min-fresh <= max-age + max-stale時,表示雖然緩存已經過期了,但是仍然可用,響應頭會挂110 警告代碼;
c. age+min-fresh > max-age + max-stale時,表示緩存過期不可用,必須重新請求拉取資料。
-
對比緩存相關屬性
響應頭除了會傳回Cache-control字段還會有其他的,主要是:ETag、If-Modified、If-Modified-Since、If-None-Match;
緩存字段名 | 含義或用途 |
---|---|
ETag | 是伺服器對某個請求的響應,目前的資源的一個特定辨別 |
If-None-Match | 是客服端再次請求伺服器時,請求的這個資源的辨別 |
這兩個是一對,都是資源辨別,一個是第一次請求,服務端傳給用戶端的資源的代号;
一個是下次用戶端再請求時,回傳給服務端,要擷取的資源的代号。
緩存字段名 | 含義或用途 |
---|---|
If-Modified | 是伺服器響應的資源的時間辨別,是截止到響應為止,資源最新被修改的時間 |
If-Modified-Since | 是用戶端再次請求資源時,回傳給伺服器的用戶端目前的資源時間辨別。 1. 若伺服器對應資源(相同ETag)的最新被修改時間變化了(If-Modified > If-Modified-Since),服務端将重新下發新的資源; 2. 若伺服器對應資源最新被修改時間未變,說明資源未變,傳回304直接用cache |
這兩個也是一對,是一對各自持有的時間辨別。用來判斷資源是否修改。
總結:Cache-control 字段規定了是否緩存、緩存在哪、緩存逾時多久(過期時間);ETag/If-Modified系列确定了資源有沒有變化。
Cookies、Session、Token
Cookies、Session、Token都是為解決無狀态問題出現的,各有差别。
Cookies在服務端的響應頭中設定Set-cookies配置
Cookies是将狀态資料儲存在用戶端,在每次請求都自動帶上(對範圍有要求,隻能帶上>=的),這種的缺點是每次通路相同的伺服器頁面就會帶上,缺乏對使用者身份的驗證。
Session是服務端給用戶端配一個唯一的session id來标記用戶端,隻有session id由用戶端儲存,其餘資料都儲存在服務端。服務端每次根據用戶端請求時送出的session id在自己的散清單中查詢,來确定用戶端身份和資料。
session id的儲存形式可以是用戶端cookies儲存或者請求時作為參數的形式(不完全依靠cookies);
這種方式當遇到分布式服務,需要給各個主機拷貝session散清單,或者提供一台專門建立、儲存、查詢、删除session id的伺服器管理。
缺點就是:拷貝過程繁瑣,或者一旦專門服務挂了,整個系統就當機了。
Token就是專門針對Session的缺點提供的一種方案,由服務端密鑰和加密算法生成字元串并簽名後,授權給用戶端,用戶端隻需要儲存這個字元串,每次請求時上傳,由服務端解密、校驗簽名即可獲得使用者身份和狀态。