[TOC]
# 前言
本文將總結后臺開發中的核心網絡知識。主要圍繞網絡層、傳輸層、應用層,核心為 TCP 和 HTTP 兩部分。
參考資料:
* 《計算機網絡原理 創新教程》(韓立剛主編)
* 《自頂向下計算機網絡》(第4版)
* 部分配圖來自:[CyC2018/CS-Notes](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/CyC2018/CS-Notes)
# 第一部分:傳輸層
## 1\. 說一下OSI七層模型 TCP/IP四層模型 五層協議
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/assets/1536486064767.png)
### (1)五層協議
* **應用層**:提供用戶接口,特指能夠發起網絡流量的程序,比如客戶端程序:QQ,MSN,瀏覽器等;服務器程序:web服務器,郵件服務器,流媒體服務器等等。數據單位為報文。
* **運輸層**:提供的是進程間的通用數據傳輸服務。由于應用層協議很多,定義通用的運輸層協議就可以支持不斷增多的應用層協議。運輸層包括兩種協議:
* 傳輸控制協議 TCP,提供面向連接、可靠的數據傳輸服務,數據單位為報文段;
* 用戶數據報協議 UDP,提供無連接、盡最大努力的數據傳輸服務,數據單位為用戶數據報。
* TCP 主要提供完整性服務,UDP 主要提供及時性服務。
* **網絡層**:為主機間提供數據傳輸服務,而運輸層協議是為主機中的進程提供服務。網絡層把運輸層傳遞下來的報文段或者用戶數據報封裝成分組。(負責選擇最佳路徑 規劃IP地址)
* 路由器查看數據包目標IP地址,根據路由表為數據包選擇路徑。路由表中的類目可以人工添加(靜態路由)也可以動態生成(動態路由)。
* **數據鏈路層**:不同的網絡類型,發送數據的機制不同,數據鏈路層就是將數據包封裝成能夠在不同的網絡傳輸的幀。能夠進行差錯檢驗,但不糾錯,監測處錯誤丟掉該幀。
* 幀的開始和結束,透明傳輸,差錯校驗
* **物理層**:物理層解決如何在連接各種計算機的傳輸媒體上傳輸數據比特流,而不是指具體的傳輸媒體。物理層的主要任務描述為:確定與傳輸媒體的接口的一些特性,即:
* 機械特性:例接口形狀,大小,引線數目
* 電氣特性:例規定電壓范圍 ( -5V 到 +5V )
* 功能特性:例規定 -5V 表示 0,+5V 表示 1
* 過程特性:也稱規程特性,規定建立連接時各個相關部件的工作步驟
### (2)ISO七層模型中表示層和會話層功能是什么?
* **表示層**:數據壓縮、加密以及數據描述。這使得應用程序不必擔心在各臺主機中表示/存儲的內部格式(二進制、ASCII,比如亂碼)不同的問題。
* **會話層**:建立會話,如session認證、斷點續傳。通信的應用程序之間建立、維護和釋放面向用戶的連接。通信的應用程序之間建立會話,需要傳輸層建立1個或多個連接。(...后臺運行的木馬,netstat -n)
* 說明:五層協議沒有表示層和會話層,而是將這些功能留給應用程序開發者處理。
### (3)數據在各層之間的傳遞過程
在向下的過程中,需要添加下層協議所需要的首部或者尾部,而在向上的過程中不斷拆開首部和尾部。
1. 路由器只有下面三層協議,因為路由器位于網絡核心中,不需要為進程或者應用程序提供服務,因此也就不需要運輸層和應用層。
2. 交換機只有下面兩層協議
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/transfer.jpg)
### (4)TCP/IP四層模型
它只有四層,相當于五層協議中**數據鏈路層和物理層合并為網絡接口層**。
現在的 TCP/IP 體系結構不嚴格遵循 OSI 分層概念,應用層可能會直接使用 IP 層或者網絡接口層。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp_ip_4.png)
TCP/IP 協議族是一種沙漏形狀,中間小兩邊大,IP 協議在其中占用舉足輕重的地位。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp_ip_protocol_family.png)
參考資料:
* [OSI模型、TCP/IP協議棧](https://arch-long.cn/articles/network/OSI%E6%A8%A1%E5%9E%8BTCPIP%E5%8D%8F%E8%AE%AE%E6%A0%88.html)
## 2\. TCP報頭格式和UDP報頭格式
網絡層只把分組發送到目的主機,但是真正通信的并不是主機而是主機中的進程。運輸層提供了進程間的邏輯通信,運輸層向高層用戶屏蔽了下面網絡層的核心細節,使應用程序看起來像是在兩個運輸層實體之間有一條端到端的邏輯通信信道。
### (1)UDP 和 TCP 的特點
* **用戶數據報協議 UDP**(User Datagram Protocol)是無連接的,盡最大可能交付,沒有擁塞控制,面向報文(對于應用程序傳下來的報文不合并也不拆分,只是添加 UDP 首部),支持一對一、一對多、多對一和多對多的交互通信。例如:視頻傳輸、實時通信
* **傳輸控制協議 TCP**(Transmission Control Protocol)是面向連接的,提供可靠交付,有流量控制,擁塞控制,提供全雙工通信,面向字節流(把應用層傳下來的報文看成字節流,把字節流組織成大小不等的數據塊),每一條 TCP 連接只能是點對點的(一對一)。
### (2)UDP 首部格式
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/udp-head2.png)
首部字段只有 8 個字節,包括源端口、目的端口、長度、檢驗和。12 字節的偽首部是為了計算檢驗和臨時添加的。
### (3)TCP 首部格式
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp-head.png)
* **序號 seq**:用于對字節流進行編號,例如序號為 301,表示第一個字節的編號為 301,如果攜帶的數據長度為 100 字節,那么下一個報文段的序號應為 401。\[301,400\]為序號301的數據長度,下一個則為401
* **確認號 ack**:期望收到的下一個報文段的序號。例如 B 正確收到 A 發送來的一個報文段,序號為 501,攜帶的數據長度為 200 字節,因此 B 期望下一個報文段的序號為 701,B 發送給 A 的確認報文段中確認號就為 701。
* **數據偏移**:指的是數據部分距離報文段起始處的偏移量,實際上指的是首部的長度。
* **確認 ACK**:當 ACK=1 時確認號字段有效,否則無效。TCP 規定,在連接建立后所有傳送的報文段都必須把 ACK 置 1。
* **同步 SYN**:在連接建立時用來同步序號。當 SYN=1,ACK=0 時表示這是一個連接請求報文段。若對方同意建立連接,則響應報文中 SYN=1,ACK=1。
* **終止 FIN**:用來釋放一個連接,當 FIN=1 時,表示此報文段的發送方的數據已發送完畢,并要求釋放連接。
* **窗口**:窗口值作為接收方讓發送方設置其發送窗口的依據。之所以要有這個限制,是因為接收方的數據緩存空間是有限的。
參考資料:
* [計算機網絡-運輸層-筆記 | SamanthaChen's Blog](https://samanthachen.github.io/2016/08/15/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C3/)
## 3\. TCP三次握手?那四次揮手呢?如何保障可靠傳輸
### (1)三次握手
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp-3.png)
**假設 A 為客戶端,B 為服務器端。**
* 首先 B 處于 LISTEN(監聽)狀態,等待客戶的連接請求。
* A 向 B 發送連接請求報文段,SYN=1,ACK=0,選擇一個初始的序號 seq = x。
* B 收到連接請求報文段,如果同意建立連接,則向 A 發送連接確認報文段,SYN=1,ACK=1,確認號為 x+1,同時也選擇一個初始的序號 seq = y。
* A 收到 B 的連接確認報文段后,還要向 B 發出確認,確認號為 ack = y+1,序號為 seq = x+1。
* A 的 TCP 通知上層應用進程,連接已經建立。
* B 收到 A 的確認后,連接建立。
* B 的 TCP 收到主機 A 的確認后,也通知其上層應用進程:TCP 連接已經建立。
### (2)為什么TCP連接需要三次握手,兩次不可以嗎,為什么
**為了防止已失效的連接請求報文段突然又傳送到了服務端,占用服務器資源。 (假設主機A為客戶端,主機B為服務器端)**
現假定出現一種異常情況,即A發出的第一個連接請求報文段并沒有丟失,而是在某些網絡節點長時間滯留了,以致延誤到連接釋放以后的某個時間才到B。本來這是一個已失效的報文段。但是B收到此失效的連接請求報文段后,就誤認為是A有發出一次新的連接請求。于是就向A發出確認報文段,同意建立連接。假定不采用三次握手,那么只要B發出確認,新的連接就建立了。
由于現在A并沒有發出建立連接的請求,因此不會理睬B的確認,也不會向B發送數據。但B卻以為新的運輸連接已經建立了,并一直等待A發來數據。B的許多資源就這樣白白浪費了。
采用三次握手的辦法可以防止上述現象的發生。例如在剛才的情況下,A不會向B的確認發出確認。B由于收不到確認,就知道A并沒有要求建立連接。
### (3)四次揮手
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp-4.png)
數據傳輸結束后,通信的雙方都可釋放連接。現在 A 的應用進程先向其 TCP 發出連接釋放報文段,并停止再發送數據,主動關閉 TCP連接。
* A 把連接釋放報文段首部的 FIN = 1,其序號 seq = u,等待 B 的確認。
* B 發出確認,確認號 ack = u+1,而這個報文段自己的序號 seq = v。(TCP 服務器進程通知高層應用進程)
* 從 A 到 B 這個方向的連接就釋放了,TCP 連接處于半關閉狀態。A 不能向 B 發送數據;B 若發送數據,A 仍要接收。
* 當 B 不再需要連接時,發送連接釋放請求報文段,FIN=1。
* A 收到后發出確認,進入 TIME-WAIT 狀態,等待 2 MSL(2\*2 = 4 mins)時間后釋放連接。
* B 收到 A 的確認后釋放連接。
### (4)四次揮手的原因
客戶端發送了 FIN 連接釋放報文之后,服務器收到了這個報文,就進入了 CLOSE-WAIT 狀態。這個狀態是為了讓服務器端發送還未傳送完畢的數據,傳送完畢之后,服務器會發送 FIN 連接釋放報文。
### (5)TIME\_WAIT
> MSL是Maximum Segment Lifetime英文的縮寫,中文可以譯為 “報文最大生存時間”,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。2MSL = 2\*2mins = 4mins
客戶端接收到服務器端的 FIN 報文后進入此狀態,此時并不是直接進入 CLOSED 狀態,還需要等待一個時間計時器設置的時間 2MSL。這么做有兩個理由:
* 確保最后一個確認報文段能夠到達。如果 B 沒收到 A 發送來的確認報文段,那么就會重新發送連接釋放請求報文段,A 等待一段時間就是為了處理這種情況的發生。
* 等待一段時間是為了讓本連接持續時間內所產生的所有報文段都從網絡中消失,使得下一個新的連接不會出現舊的連接請求報文段。
### (6)如何保證可靠傳輸
**【詳細請查閱】:《計算機網絡原理 創新教程》P356——8.4節,可靠傳輸**
* 應用數據被分割成TCP認為最適合發送的數據塊。?
* **超時重傳**:當TCP發出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發這個報文段。
* TCP給發送的每一個包進行編號,接收方對數據包進行排序,把有序數據傳送給應用層。?
* **校驗和**:TCP將保持它首部和數據的檢驗和。這是一個端到端的檢驗和,目的是檢測數據在傳輸過程中的任何變化。如果收到段的檢驗和有差錯,TCP將丟棄這個報文段和不確認收到此報文段。
* TCP的接收端會丟棄重復的數據。
* **流量控制**:TCP連接的每一方都有固定大小的緩沖空間,TCP的接收端只允許發送端發送接收端緩沖區能接納的我數據。當接收方來不及處理發送方的數據,能提示發送方降低發送的速率,防止包丟失。TCP使用的流量控制協議是可變大小的滑動窗口協議。
* **擁塞控制**:當網絡擁塞時,減少數據的發送。
### (7)TCP連接狀態?
* CLOSED:初始狀態。
* LISTEN:服務器處于監聽狀態。
* SYN\_SEND:客戶端socket執行CONNECT連接,發送SYN包,進入此狀態。
* SYN\_RECV:服務端收到SYN包并發送服務端SYN包,進入此狀態。
* ESTABLISH:表示連接建立。客戶端發送了最后一個ACK包后進入此狀態,服務端接收到ACK包后進入此狀態。
* FIN\_WAIT\_1:終止連接的一方(通常是客戶機)發送了FIN報文后進入。等待對方FIN。
* CLOSE\_WAIT:(假設服務器)接收到客戶機FIN包之后等待關閉的階段。在接收到對方的FIN包之后,自然是需要立即回復ACK包的,表示已經知道斷開請求。但是本方是否立即斷開連接(發送FIN包)取決于是否還有數據需要發送給客戶端,若有,則在發送FIN包之前均為此狀態。
* FIN\_WAIT\_2:此時是半連接狀態,即有一方要求關閉連接,等待另一方關閉。客戶端接收到服務器的ACK包,但并沒有立即接收到服務端的FIN包,進入FIN\_WAIT\_2狀態。
* LAST\_ACK:服務端發動最后的FIN包,等待最后的客戶端ACK響應,進入此狀態。
* TIME\_WAIT:客戶端收到服務端的FIN包,并立即發出ACK包做最后的確認,在此之后的2MSL時間稱為TIME\_WAIT狀態。
### (8)TCP和HTTP
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/tcp-and-http.jpg)
## 4\. TCP連接中如果斷電怎么辦
TCP新手誤區--心跳的意義 - CSDN博客[https://blog.csdn.net/bjrxyz/article/details/71076442](https://blog.csdn.net/bjrxyz/article/details/71076442)
## 5\. TCP和UDP區別?如何改進TCP
* TCP和UDP區別
* UDP 是無連接的,即發送數據之前不需要建立連接。
* UDP?使用盡最大努力交付,即不保證可靠交付,同時也不使用擁塞控制。
* UDP 是面向報文的。UDP 沒有擁塞控制,很適合多媒體通信的要求。
* UDP 支持一對一、一對多、多對一和多對多的交互通信。
* UDP 的首部開銷小,只有 8 個字節。
* TCP 是面向連接的運輸層協議。
* 每一條 TCP 連接只能有兩個端點(endpoint),每一條 TCP?連接只能是點對點的(一對一)。
* TCP 提供可靠交付的服務。
* TCP?提供全雙工通信。
* TCP是面向字節流。??
* 首部最低20個字節。
* TCP加快傳輸效率的方法
* 采取一塊確認的機制
## 6\. TCP滑動窗口
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/sliding_win.png)
窗口是緩存的一部分,用來暫時存放字節流。發送方和接收方各有一個窗口,**接收方通過 TCP 報文段中的窗口字段告訴發送方自己的窗口大小,發送方根據這個值和其它信息設置自己的窗口大小**。
發送窗口內的字節都允許被發送,接收窗口內的字節都允許被接收。如果發送窗口左部的字節已經發送并且收到了確認,那么就將發送窗口向右滑動一定距離,直到左部第一個字節不是已發送并且已確認的狀態;接收窗口的滑動類似,接收窗口左部字節已經發送確認并交付主機,就向右滑動接收窗口。
接收窗口只會對窗口內最后一個按序到達的字節進行確認,例如接收窗口已經收到的字節為 {31, 34, 35},其中 {31} 按序到達,而 {32, 33} 就不是,因此只對字節 31 進行確認。發送方得到一個字節的確認之后,就知道這個字節之前的所有字節都已經被接收。
**以下進行滑動窗口模擬**
在 TCP 中,**滑動窗口是為了實現流量控制**。如果對方發送數據過快,接收方就來不及接收,接收方就需要通告對方,減慢數據的發送。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/sliding_windows.png)
* **發送方接收到了對方發來的報文 ack = 33, win = 10,知道對方收到了 33 號前的數據**,現在期望接收 \[33, 43) 號數據。發送方連續發送了 4 個報文段假設為 A, B, C, D, 分別攜帶 \[33, 35), \[35, 36), \[36, 38), \[38, 41) 號數據。
* 接收方接收到了報文段 A, C,但是沒收到 B 和 D,也就是只收到了 \[33, 35) 和 \[36, 38) 號數據。接收方發送回對報文段 A 的確認:ack = 35, win = 10。
* 發送方收到了 ack = 35, win = 10,對方期望接收 \[35, 45) 號數據。接著發送了一個報文段 E,它攜帶了 \[41, 44) 號數據。
* 接收方接收到了報文段 B: \[35, 36), D:\[38, 41),接收方發送對 D 的確認:ack = 41, win = 10. (這是一個累積確認)
* 發送方收到了 ack = 41, win = 10,對方期望接收 \[41, 51) 號數據。
* ……
* 需要注意的是,接收方接收 tcp 報文的順序是不確定的,并非是一定先收到 35 再收到 36,也可能是先收到 36,37,再收到 35.
參考資料:
* [20-TCP 協議(滑動窗口——基礎) - CSDN博客](https://blog.csdn.net/q1007729991/article/details/70142341)
* [21-TCP 協議(滑動窗口——抓包分析) - CSDN博客](https://blog.csdn.net/q1007729991/article/details/70143062)
* [TCP 的那些事兒(下) | | 酷 殼 - CoolShell](https://coolshell.cn/articles/11609.html)
## 7\. TCP流量控制
流量控制是為了控制發送方發送速率,保證接收方來得及接收。
接收方發送的確認報文中的窗口字段可以用來控制發送方窗口大小,從而影響發送方的發送速率。將窗口字段設置為 0,則發送方不能發送數據。
## 8\. TCP擁塞處理(Congestion Handling)
擁塞控制的一般原理
* 在某段時間,若對網絡中某資源的需求超過了該資源所能提供的可用部分,網絡的性能就要變壞——產生擁塞(congestion)。
* 出現資源擁塞的條件:對資源需求的總和 > 可用資源
* 若網絡中有許多資源同時產生擁塞,網絡的性能就要明顯變壞,整個網絡的吞吐量將隨輸入負荷的增大而下降。
如果網絡出現擁塞,分組將會丟失,此時發送方會繼續重傳,從而導致網絡擁塞程度更高。因此當出現擁塞時,應當控制發送方的速率。這一點和流量控制很像,但是出發點不同。流量控制是為了讓接收方能來得及接收,而擁塞控制是為了降低整個網絡的擁塞程度。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/congest1.png)
TCP 主要通過四種算法來進行擁塞控制:慢開始、擁塞避免、快重傳、快恢復。
發送方需要維護一個叫做擁塞窗口(cwnd)的狀態變量,注意擁塞窗口與發送方窗口的區別:擁塞窗口只是一個狀態變量,實際決定發送方能發送多少數據的是發送方窗口。
為了便于討論,做如下假設:
* 接收方有足夠大的接收緩存,因此不會發生流量控制;
* 雖然 TCP 的窗口基于字節,但是這里設窗口的大小單位為報文段。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/congest2-3.png)
### (1)慢開始與擁塞避免
發送的最初執行慢開始,令 cwnd=1,發送方只能發送 1 個報文段;當收到確認后,將 cwnd 加倍,因此之后發送方能夠發送的報文段數量為:2、4、8 ...
注意到慢開始每個輪次都將 cwnd 加倍,這樣會讓 cwnd 增長速度非常快,從而使得發送方發送的速度增長速度過快,網絡擁塞的可能也就更高。設置一個慢啟動閾值 ssthresh,當 cwnd >= ssthresh 時,進入擁塞避免,每個輪次只將 cwnd 加 1。
如果出現了超時,則令 ssthresh = cwnd/2,然后重新執行慢開始。
### (2)快重傳與快恢復
在接收方,要求每次接收到報文段都應該對最后一個已收到的有序報文段進行確認。例如已經接收到 M1 和 M2,此時收到 M4,應當發送對 M2 的確認。
在發送方,如果收到三個重復確認,那么可以知道下一個報文段丟失,此時執行快重傳,立即重傳下一個報文段。例如收到三個 M2,則 M3 丟失,立即重傳 M3。
在這種情況下,只是丟失個別報文段,而不是網絡擁塞。因此執行快恢復,令 ssthresh = cwnd/2 ,cwnd = ssthresh,注意到此時直接進入擁塞避免。慢開始和快恢復的快慢指的是 cwnd 的設定值,而不是 cwnd 的增長速率。慢開始 cwnd 設定為 1,而快恢復 cwnd 設定為 ssthresh。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/congest3-2.png)
### (3)發送窗口的上限值
發送方的發送窗口的上限值應當取為接收方窗口 rwnd 和擁塞窗口 cwnd 這兩個變量中較小的一個,即應按以下公式確定:
* 發送窗口的上限值 = Min {rwnd, cwnd}
* 當 rwnd < cwnd 時,是接收方的接收能力限制發送窗口的最大值。
* 當 cwnd < rwnd 時,則是網絡的擁塞限制發送窗口的最大值。
## 9\. 如何區分流量控制和擁塞控制
* 擁塞控制所要做的都有一個前提,就是網絡能夠承受現有的網絡負荷。
* 擁塞控制是一個全局性的過程,涉及到所有的主機、所有的路由器,以及與降低網絡傳輸性能有關的所有因素。
* 流量控制往往指在給定的發送端和接收端之間的點對點通信量的控制。
* 流量控制所要做的就是抑制發送端發送數據的速率,以便使接收端來得及接收。
* 流量控制屬于通信雙方協商;擁塞控制涉及通信鏈路全局。
* 流量控制需要通信雙方各維護一個發送窗、一個接收窗,對任意一方,接收窗大小由自身決定,發送窗大小由接收方響應的TCP報文段中窗口值確定;擁塞控制的擁塞窗口大小變化由試探性發送一定數據量數據探查網絡狀況后而自適應調整。
* 實際最終發送窗口 = min{流控發送窗口,擁塞窗口}。
## 10\. 解釋RTO,RTT和超時重傳
* **超時重傳**:發送端發送報文后若長時間未收到確認的報文則需要重發該報文。可能有以下幾種情況:
* 發送的數據沒能到達接收端,所以對方沒有響應。
* 接收端接收到數據,但是ACK報文在返回過程中丟失。
* 接收端拒絕或丟棄數據。
* **RTO**:從上一次發送數據,因為長期沒有收到ACK響應,到下一次重發之間的時間。就是重傳間隔。
* 通常每次重傳RTO是前一次重傳間隔的兩倍,計量單位通常是RTT。例:1RTT,2RTT,4RTT,8RTT......
* 重傳次數到達上限之后停止重傳。
* **RTT**:數據從發送到接收到對方響應之間的時間間隔,即數據報在網絡中一個往返用時。大小不穩定。
## 11\. 停止等待和超時重傳
## 12\. 從輸入網址到獲得頁面的網絡請求過程
* 查詢 DNS
* 瀏覽器搜索自身的DNS緩存
* 搜索操作系統的DNS緩存,本地host文件查詢
* 如果 DNS 服務器和我們的主機在同一個子網內,系統會按照下面的 ARP 過程對 DNS 服務器進行 ARP查詢
* 如果 DNS 服務器和我們的主機在不同的子網,系統會按照下面的 ARP 過程對默認網關進行查詢
* 瀏覽器獲得域名對應的IP地址后,發起HTTP三次握手
* TCP/IP連接建立起來后,瀏覽器就可以向服務器發送HTTP請求了
* TLS 握手
* 客戶端發送一個`ClientHello`消息到服務器端,消息中同時包含了它的 Transport Layer Security (TLS) 版本,可用的加密算法和壓縮算法。
* 服務器端向客戶端返回一個`ServerHello`消息,消息中包含了服務器端的TLS版本,服務器所選擇的加密和壓縮算法,以及數字證書認證機構(Certificate Authority,縮寫 CA)簽發的服務器公開證書,證書中包含了公鑰。客戶端會使用這個公鑰加密接下來的握手過程,直到協商生成一個新的對稱密鑰
* 客戶端根據自己的信任CA列表,驗證服務器端的證書是否可信。如果認為可信,客戶端會生成一串偽隨機數,使用服務器的公鑰加密它。這串隨機數會被用于生成新的對稱密鑰
* 服務器端使用自己的私鑰解密上面提到的隨機數,然后使用這串隨機數生成自己的對稱主密鑰
* 客戶端發送一個`Finished`消息給服務器端,使用對稱密鑰加密這次通訊的一個散列值
* 服務器端生成自己的 hash 值,然后解密客戶端發送來的信息,檢查這兩個值是否對應。如果對應,就向客戶端發送一個`Finished`消息,也使用協商好的對稱密鑰加密
* 從現在開始,接下來整個 TLS 會話都使用對稱秘鑰進行加密,傳輸應用層(HTTP)內容
* HTTP 服務器請求處理
HTTPD(HTTP Daemon)在服務器端處理請求/響應。最常見的 HTTPD 有 Linux 上常用的 Apache 和 nginx,以及 Windows 上的 IIS。
* HTTPD 接收請求
* * 服務器把請求拆分為以下幾個參數:
HTTP 請求方法(`GET`,`POST`,`HEAD`,`PUT`,`DELETE`,`CONNECT`,`OPTIONS`, 或者`TRACE`)。直接在地址欄中輸入 URL 這種情況下,使用的是 GET 方法域名:google.com請求路徑/頁面:/ (我們沒有請求google.com下的指定的頁面,因此 / 是默認的路徑)
* 服務器驗證其上已經配置了 google.com 的虛擬主機
* 服務器驗證 google.com 接受 GET 方法
* 服務器驗證該用戶可以使用 GET 方法(根據 IP 地址,身份信息等)
* 如果服務器安裝了 URL 重寫模塊(例如 Apache 的 mod\_rewrite 和 IIS 的 URL Rewrite),服務器會嘗試匹配重寫規則,如果匹配上的話,服務器會按照規則重寫這個請求
* 服務器根據請求信息獲取相應的響應內容,這種情況下由于訪問路徑是 "/" ,會訪問首頁文件(你可以重寫這個規則,但是這個是最常用的)。
* 服務器會使用指定的處理程序分析處理這個文件,假如 Google 使用 PHP,服務器會使用 PHP 解析 index 文件,并捕獲輸出,把 PHP 的輸出結果返回給請求者
* 服務器接受到這個請求,根據路徑參數,經過后端的一些處理生成HTML頁面代碼返回給瀏覽器
* 瀏覽器拿到完整的HTML頁面代碼開始解析和渲染,如果遇到引用的外部[js](http://lib.csdn.net/base/javascript),CSS,圖片等靜態資源,它們同樣也是一個個的HTTP請求,都需要經過上面的步驟
* 瀏覽器根據拿到的資源對頁面進行渲染,最終把一個完整的頁面呈現給用戶
超詳細版本請轉向閱讀:[what-happens-when-zh\_CN](https://github.com/skyline75489/what-happens-when-zh_CN)
# 第二部分:應用層(HTTP)
## 1\. URL、URI、URN區別
* URI(Uniform Resource Identifier,統一資源標識符)
web服務器資源的名字,例如: index.html
* URL(Uniform Resource Locator,統一資源定位符)
* URN(Uniform Resource Name,統一資源名稱),例如 urn:isbn:0-486-27557-4。
URI 包含 URL 和 URN,目前 WEB 只有 URL 比較流行,所以見到的基本都是 URL。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/url_uri_urn.jpg)
## 2\. HTTP的請求和響應報文
### (1)請求報文
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/HTTP_RequestMessageExample.png)
**GET請求**
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http_request_get.png)
**POST請求**
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http_request_post.png)
### (2)響應報文
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/HTTP_ResponseMessageExample.png)
**200響應**
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http_response_200.png)
**404響應**
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http_response_400.png)
參考資料:
* [這一次,讓我們再深入一點 - HTTP報文 - 掘金](https://juejin.im/post/5a4f782c5188257326469d7c)
## 3\. HTTP狀態
服務器返回的**響應報文**中第一行為狀態行,包含了狀態碼以及原因短語,用來告知客戶端請求的結果。
| 狀態碼 | 類別 | 原因短語 |
| --- | --- | --- |
| 1XX | Informational(信息性狀態碼) | 接收的請求正在處理 |
| 2XX | Success(成功狀態碼) | 請求正常處理完畢 |
| 3XX | Redirection(重定向狀態碼) | 需要進行附加操作以完成請求 |
| 4XX | Client Error(客戶端錯誤狀態碼) | 服務器無法處理請求 |
| 5XX | Server Error(服務器錯誤狀態碼) | 服務器處理請求出錯 |
### (1)1XX 信息
* **100 Continue**:表明到目前為止都很正常,客戶端可以繼續發送請求或者忽略這個響應。
### (2)2XX 成功
* **200 OK**
* **204 No Content**:請求已經成功處理,但是返回的響應報文不包含實體的主體部分。一般在只需要從客戶端往服務器發送信息,而不需要返回數據時使用。
* **206 Partial Content**:表示客戶端進行了范圍請求。響應報文包含由 Content-Range 指定范圍的實體內容。
### (3)3XX 重定向
* **301 Moved Permanently**:永久性重定向
* **302 Found**:臨時性重定向
* **303 See Other**:和 302 有著相同的功能,但是 303 明確要求客戶端應該采用 GET 方法獲取資源。
* 注:雖然 HTTP 協議規定 301、302 狀態下重定向時不允許把 POST 方法改成 GET 方法,但是大多數瀏覽器都會在 301、302 和 303 狀態下的重定向把 POST 方法改成 GET 方法。
* **304 Not Modified**:如果請求報文首部包含一些條件,例如:If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,如果不滿足條件,則服務器會返回 304 狀態碼。
* **307 Temporary Redirect**:臨時重定向,與 302 的含義類似,但是 307 要求瀏覽器不會把重定向請求的 POST 方法改成 GET 方法。
### (4)4XX 客戶端錯誤
* **400 Bad Request**:請求報文中存在語法錯誤。
* **401 Unauthorized**:該狀態碼表示發送的請求需要有認證信息(BASIC 認證、DIGEST 認證)。如果之前已進行過一次請求,則表示用戶認證失敗。
* **403 Forbidden**:請求被拒絕,服務器端沒有必要給出拒絕的詳細理由。
* **404 Not Found**
### (5)5XX 服務器錯誤
* **500 Internal Server Error**:服務器正在執行請求時發生錯誤。
* **503 Service Unavailable**:服務器暫時處于超負載或正在進行停機維護,現在無法處理請求。
## 4\. HTTP方法
客戶端發送的**請求報文**第一行為請求行,包含了方法字段。
### (1)GET
> 獲取資源
當前網絡請求中,絕大部分使用的是 GET 方法。
### (2)HEAD
> 獲取報文首部
和 GET 方法一樣,但是不返回報文實體主體部分。
主要用于確認 URL 的有效性以及資源更新的日期時間等。
### (3)POST
> 傳輸實體主體
POST 主要用來傳輸數據,而 GET 主要用來獲取資源。
更多 POST 與 GET 的比較請見第八章。
### (4)PUT
> 上傳文件
由于自身不帶驗證機制,任何人都可以上傳文件,因此存在安全性問題,一般不使用該方法。
~~~
PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16
<p>New File</p>
~~~
### (5)PATCH
> 對資源進行部分修改
PUT 也可以用于修改資源,但是只能完全替代原始資源,PATCH 允許部分修改。
~~~
PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100
[description of changes]
~~~
### (6)DELETE
> 刪除文件
與 PUT 功能相反,并且同樣不帶驗證機制。
~~~
DELETE /file.html HTTP/1.1
~~~
### (7)OPTIONS
> 查詢支持的方法
查詢指定的 URL 能夠支持的方法。
會返回 Allow: GET, POST, HEAD, OPTIONS 這樣的內容。
### (8)CONNECT
> 要求在與代理服務器通信時建立隧道
使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通信內容加密后經網絡隧道傳輸。
~~~
CONNECT www.example.com:443 HTTP/1.1
~~~
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http_connect.jpg)
### (9)TRACE
> 追蹤路徑
服務器會將通信路徑返回給客戶端。
發送請求時,在 Max-Forwards 首部字段中填入數值,每經過一個服務器就會減 1,當數值為 0 時就停止傳輸。
通常不會使用 TRACE,并且它容易受到 XST 攻擊(Cross-Site Tracing,跨站追蹤)。
## 5\. GET和POST的區別?【阿里面經OneNote】
> 就下面的找幾個點和面試官侃侃而談即可,不可能全部都記得,想到什么講什么吧
* GET 被強制服務器支持
* 瀏覽器對URL的長度有限制,所以GET請求不能代替POST請求發送大量數據
* GET請求發送數據更小
* GET請求是不安全的
* GET請求是冪等的
* 冪等的意味著對同一URL的多個請求應該返回同樣的結果
* POST請求不能被緩存
* POST請求相對GET請求是「安全」的
* 這里安全的含義僅僅是指是非修改信息
* GET用于信息獲取,而且是安全的和冪等的
* 所謂安全的意味著該操作用于獲取信息而非修改信息。換句話說,GET 請求一般不應產生副作用。就是說,它僅僅是獲取資源信息,就像數據庫查詢一樣,不會修改,增加數據,不會影響資源的狀態。
* POST是用于修改服務器上的資源的請求
* 發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠
**引申:說完原理性的問題,我們從表面上來看看GET和POST的區別:**
* GET是從服務器上獲取數據,POST是向服務器傳送數據。 GET和 POST只是一種傳遞數據的方式,GET也可以把數據傳到服務器,他們的本質都是發送請求和接收結果。只是組織格式和數據量上面有差別,http協議里面有介紹
* GET是把參數數據隊列加到提交表單的ACTION屬性所指的URL中,值和表單內各個字段一一對應,在URL中可以看到。POST是通過HTTP POST機制,將表單內各個字段與其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址。用戶看不到這個過程。 因為GET設計成傳輸小數據,而且最好是不修改服務器的數據,所以瀏覽器一般都在地址欄里面可以看到,但POST一般都用來傳遞大數據,或比較隱私的數據,所以在地址欄看不到,能不能看到不是協議規定,是瀏覽器規定的。
* 對于GET方式,服務器端用Request.QueryString獲取變量的值,對于POST方式,服務器端用Request.Form獲取提交的數據。 沒明白,怎么獲得變量和你的服務器有關,和GET或POST無關,服務器都對這些請求做了封裝
* GET傳送的數據量較小,不能大于2KB。POST傳送的數據量較大,一般被默認為不受限制。但理論上,IIS4中最大量為80KB,IIS5中為100KB。 POST基本沒有限制,我想大家都上傳過文件,都是用POST方式的。只不過要修改form里面的那個type參數
* GET安全性非常低,POST安全性較高。 如果沒有加密,他們安全級別都是一樣的,隨便一個監聽器都可以把所有的數據監聽到。
## 6\. 如何理解HTTP協議是無狀態的
~~~
HTTP協議是無狀態的(stateless),指的是協議對于事務處理沒有記憶能力,服務器不知道客戶端是什么狀態。也就是說,打開一個服務器上的網頁和上一次打開這個服務器上的網頁之間沒有任何聯系。HTTP是一個無狀態的面向連接的協議,無狀態不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協議(無連接)。
缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。
~~~
## 7\. 什么是短連接和長連接
在HTTP/1.0中默認使用短連接。也就是說,客戶端和服務器每進行一次HTTP操作,就建立一次連接,任務結束就中斷連接。當客戶端瀏覽器訪問的某個HTML或其他類型的Web頁中包含有其他的Web資源(如JavaScript文件、圖像文件、CSS文件等),每遇到這樣一個Web資源,瀏覽器就會重新建立一個HTTP會話。
而從HTTP/1.1起,默認使用長連接,用以保持連接特性。使用長連接的HTTP協議,會在響應頭加入這行代碼:
~~~js
Connection:keep-alive
~~~
在使用長連接的情況下,當一個網頁打開完成后,客戶端和服務器之間用于傳輸HTTP數據的TCP連接不會關閉,客戶端再次訪問這個服務器時,會繼續使用這一條已經建立的連接。Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務器軟件(如Apache)中設定這個時間。實現長連接需要客戶端和服務端都支持長連接。
HTTP協議的長連接和短連接,實質上是TCP協議的長連接和短連接。
## ★ 微信二維碼登錄如何實現
## 8\. Cookie
HTTP 協議是無狀態的,主要是為了讓 HTTP 協議盡可能簡單,使得它能夠處理大量事務。HTTP/1.1 引入 Cookie 來保存狀態信息。
Cookie 是服務器發送到用戶瀏覽器并保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶并發送到服務器上。它用于告知服務端兩個請求是否來自同一瀏覽器,并保持用戶的登錄狀態。
### (1)用途
* 會話狀態管理(如用戶登錄狀態、購物車、游戲分數或其它需要記錄的信息)
* 個性化設置(如用戶自定義設置、主題等)
* 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
Cookie 曾一度用于客戶端數據的存儲,因為當時并沒有其它合適的存儲辦法而作為唯一的存儲手段,但現在隨著現代瀏覽器開始支持各種各樣的存儲方式,Cookie 漸漸被淘汰。由于服務器指定 Cookie 后,瀏覽器的每次請求都會攜帶 Cookie 數據,會帶來額外的性能開銷(尤其是在移動環境下)。新的瀏覽器 API 已經允許開發者直接將數據存儲到本地,如使用 Web storage API (本地存儲和會話存儲)或 IndexedDB。
### (2)創建過程
服務器發送的響應報文包含 Set-Cookie 首部字段,客戶端得到響應報文后把 Cookie 內容保存到瀏覽器中。
~~~
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
~~~
客戶端之后對同一個服務器發送請求時,會從瀏覽器中讀出 Cookie 信息通過 Cookie 請求首部字段發送給服務器。
~~~
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
~~~
### (3)分類
* 會話期 Cookie:瀏覽器關閉之后它會被自動刪除,也就是說它僅在會話期內有效。
* 持久性 Cookie:指定一個特定的過期時間(Expires)或有效期(max-age)之后就成為了持久性的 Cookie。
~~~
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
~~~
###(4)JavaScript 獲取 Cookie
通過`Document.cookie`屬性可創建新的 Cookie,也可通過該屬性訪問非 HttpOnly 標記的 Cookie。
~~~
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
~~~
### (5)Secure 和 HttpOnly
標記為 Secure 的 Cookie 只應通過被 HTTPS 協議加密過的請求發送給服務端。但即便設置了 Secure 標記,敏感信息也不應該通過 Cookie 傳輸,因為 Cookie 有其固有的不安全性,Secure 標記也無法提供確實的安全保障。
標記為 HttpOnly 的 Cookie 不能被 JavaScript 腳本調用。因為跨域腳本 (XSS) 攻擊常常使用 JavaScript 的`Document.cookie`API 竊取用戶的 Cookie 信息,因此使用 HttpOnly 標記可以在一定程度上避免 XSS 攻擊。
~~~
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
~~~
### (6)作用域
Domain 標識指定了哪些主機可以接受 Cookie。如果不指定,默認為當前文檔的主機(不包含子域名)。如果指定了 Domain,則一般包含子域名。例如,如果設置 Domain=mozilla.org,則 Cookie 也包含在子域名中(如 developer.mozilla.org)。
Path 標識指定了主機下的哪些路徑可以接受 Cookie(該 URL 路徑必須存在于請求 URL 中)。以字符 %x2F ("/") 作為路徑分隔符,子路徑也會被匹配。例如,設置 Path=/docs,則以下地址都會匹配:
* /docs
* /docs/Web/
* /docs/Web/HTTP
## 9\. Session
除了可以將用戶信息通過 Cookie 存儲在用戶瀏覽器中,也可以利用 Session 存儲在服務器端,存儲在服務器端的信息更加安全。
Session 可以存儲在服務器上的文件、數據庫或者內存中,現在最常見的是將 Session 存儲在內存型數據庫中,比如 Redis。
使用 Session 維護用戶登錄的過程如下:
* 用戶進行登錄時,用戶提交包含用戶名和密碼的表單,放入 HTTP 請求報文中;
* 服務器驗證該用戶名和密碼;
* 如果正確則把用戶信息存儲到 Redis 中,它在 Redis 中的 ID 稱為 Session ID;
* 服務器返回的響應報文的 Set-Cookie 首部字段包含了這個 Session ID,客戶端收到響應報文之后將該 Cookie 值存入瀏覽器中;
* 客戶端之后對同一個服務器進行請求時會包含該 Cookie 值,服務器收到之后提取出 Session ID,從 Redis 中取出用戶信息,繼續之后的業務操作。
應該注意 Session ID 的安全性問題,不能讓它被惡意攻擊者輕易獲取,那么就不能產生一個容易被猜到的 Session ID 值。此外,還需要經常重新生成 Session ID。在對安全性要求極高的場景下,例如轉賬等操作,除了使用 Session 管理用戶狀態之外,還需要對用戶進行重新驗證,比如重新輸入密碼,或者使用短信驗證碼等方式。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/session_mechanism.png)
## 10\. 瀏覽器禁用 Cookie
此時無法使用 Cookie 來保存用戶信息,只能使用 Session。除此之外,不能再將 Session ID 存放到 Cookie 中,而是使用 URL 重寫技術,將 Session ID 作為 URL 的參數進行傳遞。
## 11\. Cookie 與 Session 選擇
* Cookie 只能存儲 ASCII 碼字符串,而 Session 則可以存取任何類型的數據,因此在考慮數據復雜性時首選 Session;
* Cookie 存儲在瀏覽器中,容易被惡意查看。如果非要將一些隱私數據存在 Cookie 中,可以將 Cookie 值進行加密,然后在服務器進行解密;
* 對于大型網站,如果用戶所有的信息都存儲在 Session 中,那么開銷是非常大的,因此不建議將所有的用戶信息都存儲到 Session 中。
## 12\. HTTPs安全性
**HTTP 有以下安全性問題:**
* 使用明文進行通信,內容可能會被竊聽;
* 不驗證通信方的身份,通信方的身份有可能遭遇偽裝;
* 無法證明報文的完整性,報文有可能遭篡改。
HTTPs(Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。
HTTPs 并不是新協議,而是讓 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信。也就是說 HTTPs 使用了隧道進行通信。
通過使用 SSL,HTTPs 具有了加密(防竊聽)、認證(防偽裝)和完整性保護(防篡改)。
[](https://github.com/CyC2018/Interview-Notebook/raw/master/pics/ssl-offloading.jpg)
### (1)對稱密鑰加密
對稱密鑰加密(Symmetric-Key Encryption),加密和解密使用同一密鑰。
* 優點:運算速度快;
* 缺點:無法安全地將密鑰傳輸給通信方。
[](https://raw.githubusercontent.com/CyC2018/Interview-Notebook/master/pics/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png)
### (2)非對稱密鑰加密
非對稱密鑰加密,又稱公開密鑰加密(Public-Key Encryption),加密和解密使用不同的密鑰。
公開密鑰所有人都可以獲得,通信發送方獲得接收方的公開密鑰之后,就可以使用公開密鑰進行加密,接收方收到通信內容后使用私有密鑰解密。
非對稱密鑰除了用來加密,還可以用來進行簽名。因為私有密鑰無法被其他人獲取,因此通信發送方使用其私有密鑰進行簽名,通信接收方使用發送方的公開密鑰對簽名進行解密,就能判斷這個簽名是否正確。
* 優點:可以更安全地將公開密鑰傳輸給通信發送方;
* 缺點:運算速度慢。
[](https://raw.githubusercontent.com/CyC2018/Interview-Notebook/master/pics/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png)
### (3)HTTPs 采用的加密方式
HTTPs 采用混合的加密機制,使用非對稱密鑰加密用于傳輸對稱密鑰來保證安全性,之后使用對稱密鑰加密進行通信來保證效率。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/How-HTTPS-Works2.png)
## 13\. SSL/TLS協議的握手過程
我們知道,HTTP 協議都是明文傳輸內容,在早期只展示靜態內容時沒有問題。伴隨著互聯網的快速發展,人們對于網絡傳輸安全性的要求也越來越高,HTTPS 協議因此出現。如上圖所示,在 HTTPS 加密中真正起作用的其實是 SSL/TLS 協議。SSL/TLS 協議作用在 HTTP 協議之下,對于上層應用來說,原來的發送接收數據流程不變,這就很好地兼容了老的 HTTP 協議,這也是軟件開發中分層實現的體現。
### SSL (Secure Socket Layer,安全套接字層)
SSL為Netscape所研發,用以保障在Internet上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程中不會被截取,當前為3.0版本。
SSL協議可分為兩層: SSL記錄協議(SSL Record Protocol):它建立在可靠的傳輸協議(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能的支持。 SSL握手協議(SSL Handshake Protocol):它建立在SSL記錄協議之上,用于在實際的數據傳輸開始前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。
### TLS (Transport Layer Security,傳輸層安全協議)
用于兩個應用程序之間提供保密性和數據完整性。 TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任務組)制定的一種新的協議,它建立在SSL 3.0協議規范之上,是SSL 3.0的后續版本,可以理解為SSL 3.1,它是寫入了 RFC 的。該協議由兩層組成: TLS 記錄協議(TLS Record)和 TLS 握手協議(TLS Handshake)。較低的層為 TLS 記錄協議,位于某個可靠的傳輸協議(例如 TCP)上面。
SSL/TLS 握手是為了**安全**地協商出一份**對稱加密**的秘鑰,這個過程很有意思,下面我們一起來了解一下。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/https_com.png)
### (1)client hello
握手第一步是客戶端向服務端發送 Client Hello 消息,這個消息里包含了一個客戶端生成的隨機數**Random1**、客戶端支持的**加密套件**(Support Ciphers)和 SSL Version 等信息。
### (2)server hello
第二步是服務端向客戶端發送 Server Hello 消息,這個消息會從 Client Hello 傳過來的 Support Ciphers 里確定一份加密套件,這個套件決定了后續加密和生成摘要時具體使用哪些算法,另外還會生成一份隨機數**Random2**。注意,至此客戶端和服務端都擁有了兩個隨機數(Random1+ Random2),這兩個隨機數會在后續生成對稱秘鑰時用到。
### (3)server certificate
這一步是服務端將自己的證書下發給客戶端,讓客戶端驗證自己的身份,客戶端驗證通過后取出證書中的公鑰。
### (4)Server Hello Done
Server Hello Done 通知客戶端 Server Hello 過程結束。
### (5)Client Key Exchange
上面客戶端根據服務器傳來的公鑰生成了**PreMaster Key**,Client Key Exchange 就是將這個 key 傳給服務端,服務端再用自己的私鑰解出這個**PreMaster Key**得到客戶端生成的**Random3**。至此,客戶端和服務端都擁有**Random1**+**Random2**+**Random3**,兩邊再根據同樣的算法就可以生成一份秘鑰,握手結束后的應用層數據都是使用這個秘鑰進行對稱加密。
為什么要使用三個隨機數呢?這是因為 SSL/TLS 握手過程的數據都是明文傳輸的,并且多個隨機數種子來生成秘鑰不容易被暴力破解出來。
### (6)Change Cipher Spec(Client)
這一步是客戶端通知服務端后面再發送的消息都會使用前面協商出來的秘鑰加密了,是一條事件消息。
### (7)Finished(Client)
客戶端發送Finished報文。該報文包含連接至今全部報文的整理校驗值。這次握手協議是否能成功,要以服務器是否能夠正確解密該報文作為判定標準。
### (8)Change Cipher Spec(Server)
服務器同樣發送Change Cipher Spec報文給客戶端
### (9)Finished(Server)
服務器同樣發送Finished報文給客戶端
### (10-11)Application Data
到這里,雙方已安全地協商出了同一份秘鑰,所有的應用層數據都會用這個秘鑰加密后再通過 TCP 進行可靠傳輸。
### (12)Alert:warning, close notify
最后由客戶端斷開連接。斷開連接時,發送close\_notify報文。上圖做了一些省略,在這步之后再發送一種叫做MAC(Message Authentication Code)的報文摘要。MAC能夠查知報文是否遭到篡改,從而保護報文的完整性。
### (13)demand client certificate
Certificate Request 是服務端要求客戶端上報證書,這一步是可選的,對于安全性要求高的場景會用到。
### check server certificate
客戶端收到服務端傳來的證書后,先從 CA 驗證該證書的合法性,驗證通過后取出證書中的服務端公鑰,再生成一個隨機數**Random3**,再用服務端公鑰非對稱加密**Random3**生成**PreMaster Key**。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/SSL_handshake.png)
參考資料:
* [SSL\_handshake\_with\_two\_way\_authentication\_with\_certificates.svg](https://upload.wikimedia.org/wikipedia/commons/a/ae/SSL_handshake_with_two_way_authentication_with_certificates.svg)
* [SSL/TLS 握手過程詳解 - 簡書](https://www.jianshu.com/p/7158568e4867)
* [圖解SSL/TLS協議 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)
* [【慕課視頻】ios開發網絡協議https請求視頻教程](https://www.imooc.com/learn/969)
* [學習HTTP/2 | levy](http://levy.work/2017-12-28-http2/)
* [詳解 https 是如何確保安全的? - 后端 - 掘金](https://juejin.im/entry/570469035bbb500051d4eceb)
## 14\. 數字簽名、數字證書、SSL、https是什么關系?
HTTPS 是建立在密碼學基礎之上的一種安全通信協議,嚴格來說是基于 HTTP 協議和 SSL/TLS 的組合。理解 HTTPS 之前有必要弄清楚一些密碼學的相關基礎概念,比如:明文、密文、密碼、密鑰、對稱加密、非對稱加密、信息摘要、數字簽名、數字證書。接下來我會逐個解釋這些術語,文章里面提到的『數據』、『消息』都是同一個概念,表示用戶之間通信的內容載體,此外文章中提到了以下幾個角色:
* Alice:消息發送者
* Bob:消息接收者
* Attacker:中間攻擊者
* Trent:第三方認證機構
### 密碼
密碼學中的“密碼”術語與網站登錄時用的密碼(password)是不一樣的概念,password 翻譯過來其實是“口令”,它是用于認證用途的一組文本字符串。
而密碼學中的密碼(cipher)是一套算法(algorithm),這套算法用于對消息進行加密和解密,從明文到密文的過程稱之為加密,密文反過來生成明文稱之為解密,加密算法與解密算法合在一起稱為密碼算法。
### 密鑰
密鑰(key)是在使用密碼算法過程中輸入的一段參數。同一個明文在相同的密碼算法和不同的密鑰計算下會產生不同的密文。很多知名的密碼算法都是公開的,密鑰才是決定密文是否安全的重要參數,通常密鑰越長,破解的難度越大,比如一個8位的密鑰最多有256種情況,使用窮舉法,能非常輕易的破解。根據密鑰的使用方法,密碼可分為對稱加密和公鑰加密。
### 對稱加密
對稱密鑰(Symmetric-key algorithm)又稱為共享密鑰加密,加密和解密使用相同的密鑰。常見的對稱加密算法有DES、3DES、AES、RC5、RC6。對稱密鑰的優點是計算速度快,但是它有缺點,接收者需要發送者告知密鑰才能解密,因此密鑰如何安全的發送給接收者成為了一個問題。
[](https://camo.githubusercontent.com/79601fe75b0b92a8037594c5ef7b5d66f40ddcf8/68747470733a2f2f706963332e7a68696d672e636f6d2f38302f76322d39356632356331326165343036646132326537633462343230356134393166625f722e6a7067)
Alice 給 Bob 發送數據時,把數據用對稱加密后發送給 Bob,發送過程中由于對數據進行了加密,因此即使有人竊取了數據也沒法破解,因為它不知道密鑰是什么。但是同樣的問題是 Bob 收到數據后也一籌莫展,因為它也不知道密鑰是什么,那么 Alice 是不是可以把數據和密鑰一同發給 Bob 呢。當然不行,一旦把密鑰和密鑰一起發送的話,那就跟發送明文沒什么區別了,因為一旦有人把密鑰和數據同時獲取了,密文就破解了。所以對稱加密的密鑰配是個問題。如何解決呢,公鑰加密是一個辦法。
### 公鑰加密(非對稱加密)
公開密鑰加密(public-key cryptography)簡稱公鑰加密,這套密碼算法包含配對的密鑰對,分為加密密鑰和解密密鑰。發送者用加密密鑰進行加密,接收者用解密密鑰進行解密。加密密鑰是公開的,任何人都可以獲取,因此加密密鑰又稱為公鑰(public key),解密密鑰不能公開,只能自己使用,因此它又稱為私鑰(private key)。常見的公鑰加密算法有 RSA。
還是以Alice 給 Bob 發送數據為例,公鑰加密算法由接收者 Bob 發起
1. Bob 生成公鑰和私鑰對,私鑰自己保存,不能透露給任何人。
2. Bob 把公鑰發送給 Alice,發送過程中即使被人竊取也沒關系
3. Alice 用公鑰把數據進行加密,并發送給 Bob,發送過程中被人竊取了同樣沒關系,因為沒有配對的私鑰進行解密是沒法破解的
4. Bob 用配對的私鑰解密。
[](https://camo.githubusercontent.com/a2e3a3a2bd133525f95303b19efc2d583c170bec/68747470733a2f2f706963342e7a68696d672e636f6d2f38302f76322d35626435303462383263636338376165363433613664366530393537396631335f722e6a7067)
雖然公鑰加密解決了密鑰配送的問題,但是你沒法確認公鑰是不是合法的,Bob 發送的公鑰你不能肯定真的是 Bob 發的,因為也有可能在 Bob 把公鑰發送給 Alice 的過程中出現中間人攻擊,把真實的公鑰掉包替換。而對于 Alice 來說完全不知。還有一個缺點是它的運行速度比對稱加密慢很多。
### 消息摘要
消息摘要(message digest)函數是一種用于判斷數據完整性的算法,也稱為散列函數或哈希函數,函數返回的值叫散列值,散列值又稱為消息摘要或者指紋(fingerprint)。這種算法是一個不可逆的算法,因此你沒法通過消息摘要反向推倒出消息是什么。所以它也稱為**單向散列函數**。下載軟件時如何確定是官方提供的完整版呢,如果有中間人在軟件里面嵌入了病毒,你也不得而知。所以我們可以使用散列函數對消息進行運算,生成散列值,通常軟件提供方會同時提供軟件的下載地址和軟件的散列值,用戶把軟件下載后在本地用相同的散列算法計算出散列值,與官方提供的散列值對比,如果相同,說明該軟件是完成的,否則就是被人修改過了。常用的散列算法有MD5、SHA。
[](https://camo.githubusercontent.com/a035b7e22ccbb171dce4b6614821b6ddc975c918/68747470733a2f2f706963332e7a68696d672e636f6d2f38302f76322d31643663663230356365333062303135313964386238366530333936383634335f722e6a7067)
下載 Eclipse 時,官方網站同時提供了軟件地址和消息摘要
[](https://camo.githubusercontent.com/87eeb1a295c364c2fdfc362b36295f6643d60ec5/68747470733a2f2f706963342e7a68696d672e636f6d2f38302f76322d66363838626334663166356132383838323339346232626539626232656465395f722e6a7067)
散列函數可以保證數據的完整性,識別出數據是否被篡改,但它并不能識別出數據是不是偽裝的,因為中間人可以把數據和消息摘要同時替換,數據雖然是完整的,但真實數據被掉包了,接收者收到的并不是發送者發的,而是中間人的。消息認證是解決數據真實性的辦法。認證使用的技術有消息認證碼和數字簽名。
### 消息認證碼
消息認證碼(message authentication code)是一種可以確認消息完整性并進行認證(消息認證是指確認消息來自正確的發送者)的技術,簡稱 MAC。消息認證碼可以簡單理解為一種與密鑰相關的單向散列函數。
[](https://camo.githubusercontent.com/8b7e1d22672d6a380872006279f56b265b0fe713/68747470733a2f2f706963312e7a68696d672e636f6d2f38302f76322d37336435326263326433383238656563346630646465356561363865666633365f722e6a7067)
Alice 給 Bob 發送消息前,先把共享密鑰(key)發送給 Bob,Alice 把消息計算出 MAC 值,連同消息一起發送給 Bob,Bob 接收到消息和 MAC 值后,與本地計算得到 MAC 值對比,如果兩者相同,就說明消息是完整的,而且可以確定是 Alice 發送的,沒有中間人偽造。不過,消息認證碼同樣會遇到對稱加密的密鑰配送問題,因此解決密鑰配送問題還是要采用公鑰加密的方式。
此外,消息認證碼還有一個無法解決的問題,Bob 雖然可以識別出消息的篡改和偽裝,但是 Alice 可以否認說:“我沒發消息,應該是 Bob 的密鑰被 Attacker 盜取了,這是 Attacker 發的吧”。Alice 這么說你還真沒什么可以反駁的,那么如何防止 Alice 不承認呢,數字簽名可以實現。
### 數字簽名
Alice 發郵件找 Bob 借1萬錢,因為郵件可以被人篡改(改成10萬),也可以被偽造(Alice 根本就沒發郵件,而是 Attacker 偽造 Alice 在發郵件),Alice 借了錢之后還可以不承認(不是我借的,我沒有簽名啊)。
**消息認證碼**可以解決篡改和偽造的問題,Alice 不承認自己借了錢時,Bob 去找第三方機構做公正,即使這樣,公正方也沒法判斷 Alice 有沒有真的借錢,因為他們倆共享了密鑰,也就是說兩個都可以計算出正確的 MAC 值,Bob 說:“明明你發的消息和 MAC 值和我自己生成的 MAC 值一樣,肯定是你發的消息”,Alice 說:“你把密鑰透露給了其他人,是他發的郵件,你找他去吧”。Alice 矢口否認。
數字簽名(Digital Signature)就可以解決否認的問題,發送消息時,Alice 和 Bob 使用不同的密鑰,把公鑰加密算法反過來使用,發送者 Alice 使用私鑰對消息進行簽名,而且只能是擁有私鑰的 Alice 可以對消息簽名,Bob 用配對的公鑰去驗證簽名,第三方機構也可以用公鑰驗證簽名,如果驗證通過,說明消息一定是 Alice 發送的,抵賴也不行,因為你只有 Alice 可以生成簽名。這就防止了否認的問題。
[](https://camo.githubusercontent.com/472ee3fefcdca46b8e4017429ed434d67205bf7b/68747470733a2f2f706963332e7a68696d672e636f6d2f38302f76322d65313831396165643130393632613964313438613862343436306436303662355f722e6a7067)
它的流程是:
第一步:發送者 Alice**把消息哈希函數處理生成消息摘要,摘要信息使用私鑰加密之后生成簽名**,連同消息一起發送給接收者 Bob。
第二步:數據經過網絡傳輸,Bob收到數據后,把簽名和消息分別提取出來。
第三步:對簽名進行驗證,驗證的過程是先把消息提取出來做同樣的Hash處理,得到消息摘要,再與 Alice 傳過來的簽名用公鑰解密,如果兩者相等,就表示簽名驗證成功,否則驗證失敗,表示不是 Alice發的。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/ca-sign.png)
### 公鑰證書
公鑰密碼在數字簽名技術里面扮演舉足輕重的角色,但是如何保證公鑰是合法的呢,如果是遭到中間人攻擊,掉包怎么辦?這個時候公鑰就應該交給一個第三方權威機構來管理,這個機構就是認證機構(Certification Authority)CA,CA 把用戶的姓名、組織、郵箱地址等個人信息收集起來,還有此人的公鑰,并由 CA 提供數字簽名生成公鑰證書(Public-Key Certificate)PKC,簡稱證書。
[](https://camo.githubusercontent.com/1eaa3b5f83030666f792d0de038d40c48993bfd1/68747470733a2f2f706963342e7a68696d672e636f6d2f38302f76322d66393664373063306438383438393231633265626236656635393166336336365f722e6a7067)
Alice 向 Bob 發送消息時,是通過 Bob 提供的公鑰加密后的數據,而 Alice 獲取的公鑰并不是由 Bob 直接給的,而是由委托一個受信任的第三方機構給的。
1. Bob 生成密鑰對,私鑰自己保管,公鑰交給認證機構 Trent。
2. Trent 經過一系列嚴格的檢查確認公鑰是 Bob 本人的
3. Trent 事先也生成自己的一套密鑰對,用自己的私鑰對 Bob 的公鑰進行數字簽名并生成數字證書。證書中包含了 Bob 的公鑰。公鑰在這里是不需要加密的,因為任何人獲取 Bob 的公鑰都沒事,只要確定是 Bob 的公鑰就行。
4. Alice 獲取 Trent 提供的證書。
5. Alice 用 Trent 提供的公鑰對證書進行簽名驗證,簽名驗證成功就表示證書中的公鑰是 Bob 的。
6. 于是 Alice 就可以用 Bob 提供的公鑰對消息加密后發送給 Bob。
7. Bob 收到密文后,用與之配對的私鑰進行解密。
至此,一套比較完善的數據傳輸方案就完成了。HTTPS(SSL/TLS)就是在這樣一套流程基礎之上建立起來的。
參考資料:
* [數字簽名、數字證書、SSL、https是什么關系? - 知乎](https://www.zhihu.com/question/52493697)
* [【Python之禪 】HTTPS 為什么更安全,先看這些](https://zhuanlan.zhihu.com/p/25324735)
## 15\. HTTP和HTTPS的區別【阿里面經OneNote】
* http是HTTP協議運行在TCP之上。所有傳輸的內容都是明文,客戶端和服務器端都無法驗證對方的身份。
* https是HTTP運行在SSL/TLS之上,SSL/TLS運行在TCP之上。所有傳輸的內容都經過加密,加密采用對稱加密,但對稱加密的密鑰用服務器方的證書進行了非對稱加密。此外客戶端可以驗證服務器端的身份,如果配置了客戶端驗證,服務器方也可以驗證客戶端的身份。
* https協議需要到ca申請證書,一般免費證書很少,需要交費。
* http是超文本傳輸協議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協議
* http和https使用的是完全不同的連接方式用的端口也不一樣,前者是80,后者是443。
* http的連接很簡單,是無狀態的
* HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議 要比http協議安全
## 16\. HTTP2.0特性
HTTP/2的通過支持請求與響應的多路復用來減少延遲,通過壓縮HTTP首部字段將協議開銷降至最低,同時增加對請求優先級和服務器端推送的支持。
### (1)二進制分幀
先來理解幾個概念:
幀:HTTP/2 數據通信的最小單位消息:指 HTTP/2 中邏輯上的 HTTP 消息。例如請求和響應等,消息由一個或多個幀組成。
流:存在于連接中的一個虛擬通道。流可以承載雙向消息,每個流都有一個唯一的整數ID。
HTTP/2 采用二進制格式傳輸數據,而非 HTTP 1.x 的文本格式,二進制協議解析起來更高效。 HTTP / 1 的請求和響應報文,都是由起始行,首部和實體正文(可選)組成,各部分之間以文本換行符分隔。HTTP/2 將請求和響應數據分割為更小的幀,并且它們采用二進制編碼。
\*\*HTTP/2 中,同域名下所有通信都在單個連接上完成,該連接可以承載任意數量的雙向數據流。\*\*每個數據流都以消息的形式發送,而消息又由一個或多個幀組成。多個幀之間可以亂序發送,根據幀首部的流標識可以重新組裝。
### (2)多路復用
多路復用,代替原來的序列和阻塞機制。所有就是請求的都是通過一個 TCP連接并發完成。 HTTP 1.x 中,如果想并發多個請求,必須使用多個 TCP 鏈接,且瀏覽器為了控制資源,還會對單個域名有 6-8個的TCP鏈接請求限制,如下圖,紅色圈出來的請求就因域名鏈接數已超過限制,而被掛起等待了一段時間。
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/pics/http2-tcp.jpg)
在 HTTP/2 中,有了二進制分幀之后,HTTP /2 不再依賴 TCP 鏈接去實現多流并行了,在 HTTP/2中:
* 同域名下所有通信都在單個連接上完成。
* 單個連接可以承載任意數量的雙向數據流。
* 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間可以亂序發送,因為根據幀首部的流標識可以重新組裝。
這一特性,使性能有了極大提升:
* **同個域名只需要占用一個 TCP 連接**,消除了因多個 TCP 連接而帶來的延時和內存消耗。
* 單個連接上可以并行交錯的請求和響應,之間互不干擾。
* 在HTTP/2中,每個請求都可以帶一個31bit的優先值,0表示最高優先級, 數值越大優先級越低。有了這個優先值,客戶端和服務器就可以在處理不同的流時采取不同的策略,以最優的方式發送流、消息和幀。
### (3)服務器推送
服務端可以在發送頁面HTML時主動推送其它資源,而不用等到瀏覽器解析到相應位置,發起請求再響應。例如服務端可以主動把JS和CSS文件推送給客戶端,而不需要客戶端解析HTML時再發送這些請求。
服務端可以主動推送,客戶端也有權利選擇是否接收。如果服務端推送的資源已經被瀏覽器緩存過,瀏覽器可以通過發送RST\_STREAM幀來拒收。主動推送也遵守同源策略,服務器不會隨便推送第三方資源給客戶端。
### (4)頭部壓縮
HTTP 1.1請求的大小變得越來越大,有時甚至會大于TCP窗口的初始大小,因為它們需要等待帶著ACK的響應回來以后才能繼續被發送。HTTP/2對消息頭采用HPACK(專為http/2頭部設計的壓縮格式)進行壓縮傳輸,能夠節省消息頭占用的網絡的流量。而HTTP/1.x每次請求,都會攜帶大量冗余頭信息,浪費了很多帶寬資源。
參考資料:
* [一文讀懂 HTTP/2 特性](https://zhuanlan.zhihu.com/p/26559480)
* \[【體驗http1.1和http2的性能對比動畫】HTTP/2: the Future of the Internet | Akamai\](HTTP/2: the Future of the Internet | Akamai)
# 第三部分:網絡層
## 1\. mac和ip怎么轉換
**ARP協議:**
將IP地址通過廣播 目標MAC地址是FF-FF-FF-FF-FF-FF 解析目標IP地址的MAC地址 掃描本網段MAC地址。
**DHCP協議:**
DHCP租約過程就是DHCP客戶機動態獲取IP地址的過程。
DHCP租約過程分為4步:
1. 客戶機請求IP(客戶機發DHCPDISCOVER廣播包);
2. 服務器響應(服務器發DHCPOFFER廣播包);
3. 客戶機選擇IP(客戶機發DHCPREQUEST廣播包);
4. 服務器確定租約(服務器發DHCPACK/DHCPNAK廣播包)。
參考資料:
* [圖解DHCP的4步租約過程-大浪淘沙-51CTO博客](http://blog.51cto.com/yuanbin/109574)
## 2\. IP地址子網劃分
| 二進制 | 十進制 |
| --- | --- |
| 1 | 1 |
| 10 | 2 |
| 100 | 4 |
| 1000 | 8 |
| 10000 | 16 |
| 100000 | 32 |
| 1000000 | 64 |
| 10000000 | 128 |
| 10000000 | 128 |
| 11000000 | 192 |
| 11100000 | 224 |
| 11110000 | 240 |
| 11111000 | 248 |
| 11111100 | 252 |
| 11111110 | 254 |
| 11111111 | 255 |
[](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/assets/%E5%AD%90%E7%BD%91%E5%88%92%E5%88%86.png)
~~~
IP分類
公有地址:
IP分類 缺省掩碼
A 1-127 /8
B 128-191 /16
C 192-223 /24
D 224-239 組播地址
E 240-247 保留地址
私有地址:
A:10.0.0.0 - 10.255.255.255
B: 172.16.0.0 - 172.31.255.255
C: 192.168.0.0 - 192.168.255.255
判斷合法的主機(IP)地址:
192.168.10.240/24 合法
192.168.10.0/24 不合法,主機位全為0,網絡地址
192.168.10.255/24 不合法,主機位全為1,子網廣播地址
255.255.255.255 不合法,網絡和主機位全為1,全網廣播地址
127.x.x.x/8 不合法,本地環回地址
172.16.3.5/24 合法
192.168.5.240/32 合法
224.10.10.10.1 不合法,組播地址
300.2.4.200/24 不合法
~~~
* IP特殊地址
* 本地環回地址:127.0.0.0 – 127.255.255.255,測試主機TCP/IP協議棧是否安裝正確。
* 本地鏈路地址:169.254.0.0 – 169.254.255.255,自動地址無法獲取時系統自動配置占位。
* 受限廣播地址:255.255.255.255,發往這個地址的數據不能跨越三層設備,但本地網絡內所有的主機都可以接收到數據
* 參考資料:
* [4internetLayer](https://canliture.github.io/s/NetworkEngineer/04internetLayer.html)
* [IP地址和子網劃分 - 混沌的光與影 - 博客園](https://www.cnblogs.com/lifi/p/7353279.html)
* \[ZenCloud2/13-網絡管理.md at a78722799508a7ac3fc7d055ff8d2d88edd0b595 · destinyplan/ZenCloud2\](ZenCloud2/13-網絡管理.md at a78722799508a7ac3fc7d055ff8d2d88edd0b595 · destinyplan/ZenCloud2 )
## 3\. 地址解析協議ARP
## 4\. 交換機和路由器的區別
1. 路由器可以給你的局域網自動分配IP,虛擬撥號,就像一個交通警察,指揮著你的電腦該往哪走,你自己不用操心那么多了。交換機只是用來分配網絡數據的。
2. 路由器在網絡層,路由器根據IP地址尋址,路由器可以處理TCP/IP協議,交換機不可以。
3. 交換機在中繼層,交換機根據MAC地址尋址。路由器可以把一個IP分配給很多個主機使用,這些主機對外只表現出一個IP。交換機可以把很多主機連起來,這些主機對外各有各的IP。
4. 路由器提供防火墻的服務,交換機不能提供該功能。集線器、交換機都是做端口擴展的,就是擴大局域網(通常都是以太網)的接入點,也就是能讓局域網可以連進來更多的電腦。路由器是用來做網間連接,也就是用來連接不同的網絡。
交換機是利用**物理地址或者說MAC地址**來確定轉發數據的目的地址。而路由器則是利用不同網絡的ID號(即IP地址)來確定數據轉發的地址。IP地址是在軟件中實現的,描述的是設備所在的網絡,有時這些第三層的地址也稱為協議地址或者網絡地址。MAC地址通常是硬件自帶的,由網卡生產商來分配的,而且已經固化到了網卡中去,一般來說是不可更改的。而IP地址則通常由網絡管理員或系統自動分配。
**路由器和交換機的區別一**:交換機是一根網線上網,但是大家上網是分別撥號,各自使用自己的寬帶,大家上網沒有影響。而路由器比交換機多了一個虛擬撥號功能,通過同一臺路由器上網的電腦是共用一個寬帶賬號,大家上網要相互影響。**路由器和交換機的區別二**:交換機工作在中繼層,交換機根據MAC地址尋址。路由器工作在網絡層,根據IP地址尋址,路由器可以處理TCP/IP協議,而交換機不可以。
**路由器和交換機的區別三**:交換機可以使連接它的多臺電腦組成局域網,如果還有代理服務器的話還可以實現同時上網功能而且局域網所有電腦是共享它的帶寬速率的,但是交換機沒有路由器的自動識別數據包發送和到達地址的功能。路由器可以自動識別數據包發送和到達的地址,路由器相當于馬路上的警察,負責交通疏導和指路的。
**路由器和交換機的區別四**:舉幾個例子,路由器是小郵局,就一個地址(IP),負責一個地方的收發(個人電腦,某個服務器,所以你家上網要這個東西),交換機是省里的大郵政中心,負責由一個地址給各個小地方的聯系。簡單的說路由器專管入網,交換機只管配送,路由路由就是給你找路讓你上網的,交換機只負責開門,交換機上面要沒有路由你是上不了網的。
**路由器和交換機的區別五**:路由器提供了防火墻的服務。路由器僅僅轉發特定地址的數據包,不傳送不支持路由協議的數據包傳送和未知目標網絡數據包的傳送,從而可以防止廣播風暴。
## 5\. 子網掩碼的作用
內網中192.168.1.199的前三組是網絡號,后一組是主機號,子網掩碼就是255.255.255.0
**首先要說明的是**:不是某個IP的網絡號和主機號決定子網掩碼是什么,而是子網掩碼決定了某個IP地址的網絡號與主機號是什么,IP地址是要搭配子網掩碼使用的。例如上面的子網掩碼決定了192.168.1.199的前三段192.168.1是網絡號,最后一段199是主機號。
我們再來理解子網掩碼的作用,先舉個例子,市面上的兩個廠家都生產電子秤,每個廠家都堅稱他們的秤最準,那你是怎么知道他們的秤到底準不準?很簡單,你去找一個 1KG 的國際千克原器,各放到他們的秤上測量,如果秤的測量值是1KG,那這把秤就是準的,**子網掩碼的作用就相當于這個大家公認的國際千克原器,是我們測量兩個IP是否屬于同一個網段的一個工具(應該說是讓你知道某個IP地址的網絡號與主機號分別是什么) 。**
**如果讓你判斷一個IP地址:192.168.1.199的網絡號和主機號分別是什么?**
請問你怎么判斷?你憑什么說192.168.1是網絡號?199是主機號?有什么根據嗎?
但是如果我給你一個IP地址是以下(帶子網掩碼)形式的:
IP:192.168.1.199
子網掩碼:255.255.255.0
那么根據大家公認的規則,你就可以得出這個IP的網絡號和主機號了,怎么算呢?
子網掩碼的長度和IP地址一樣也是一串32位的二進制數字,只不過為人類的可讀性和記憶性的方便,通常使用十進制數字來表示,例如把上面的IP地址和子網掩碼都轉換成相應的二進制就是下面這樣的:
~~~
**十進制** **二進制**
~~~
IP 地址:192.168.1.199**‐>**11000000.10101000.00000001.11000111
子網掩碼:255.255.255.0**‐>**11111111.11111111.11111111.00000000
十進制的顯示形式是給人看的,二進制的顯示形式是給計算機看的。。。
子網掩碼的左邊是網絡位,用二進制數字“1”表示,1的數目等于網絡位的長度;右邊是主機位,用二進制數字“0”表示,0的數目等于主機位的長度。
例如上面的子網掩碼255.255.255.0的 “1”的個數是左邊24位,則對應IP地址左邊的位數也是24位;
~~~
**十進制** **二進制**
~~~
IP 地址:192.168.1.199**‐>11000000.10101000.00000001**.11000111
子網掩碼:255.255.255.0**‐>11111111.11111111.11111111**.00000000
則這個IP地址的網絡號就是11000000.10101000.00000001 ,轉換成十進制就是 192.168.1,網掩碼255.255.255.0的 “0”的個數是右邊8位,則這個IP地址的主機號就是11000111,轉換成十進制就是199.
#附錄:參考資料
[OSI 七層參考模型-極客學院(4課時,47分鐘)](http://www.jikexueyuan.com/course/1400.html)
- 一.JVM
- 1.1 java代碼是怎么運行的
- 1.2 JVM的內存區域
- 1.3 JVM運行時內存
- 1.4 JVM內存分配策略
- 1.5 JVM類加載機制與對象的生命周期
- 1.6 常用的垃圾回收算法
- 1.7 JVM垃圾收集器
- 1.8 CMS垃圾收集器
- 1.9 G1垃圾收集器
- 2.面試相關文章
- 2.1 可能是把Java內存區域講得最清楚的一篇文章
- 2.0 GC調優參數
- 2.1GC排查系列
- 2.2 內存泄漏和內存溢出
- 2.2.3 深入理解JVM-hotspot虛擬機對象探秘
- 1.10 并發的可達性分析相關問題
- 二.Java集合架構
- 1.ArrayList深入源碼分析
- 2.Vector深入源碼分析
- 3.LinkedList深入源碼分析
- 4.HashMap深入源碼分析
- 5.ConcurrentHashMap深入源碼分析
- 6.HashSet,LinkedHashSet 和 LinkedHashMap
- 7.容器中的設計模式
- 8.集合架構之面試指南
- 9.TreeSet和TreeMap
- 三.Java基礎
- 1.基礎概念
- 1.1 Java程序初始化的順序是怎么樣的
- 1.2 Java和C++的區別
- 1.3 反射
- 1.4 注解
- 1.5 泛型
- 1.6 字節與字符的區別以及訪問修飾符
- 1.7 深拷貝與淺拷貝
- 1.8 字符串常量池
- 2.面向對象
- 3.關鍵字
- 4.基本數據類型與運算
- 5.字符串與數組
- 6.異常處理
- 7.Object 通用方法
- 8.Java8
- 8.1 Java 8 Tutorial
- 8.2 Java 8 數據流(Stream)
- 8.3 Java 8 并發教程:線程和執行器
- 8.4 Java 8 并發教程:同步和鎖
- 8.5 Java 8 并發教程:原子變量和 ConcurrentMap
- 8.6 Java 8 API 示例:字符串、數值、算術和文件
- 8.7 在 Java 8 中避免 Null 檢查
- 8.8 使用 Intellij IDEA 解決 Java 8 的數據流問題
- 四.Java 并發編程
- 1.線程的實現/創建
- 2.線程生命周期/狀態轉換
- 3.線程池
- 4.線程中的協作、中斷
- 5.Java鎖
- 5.1 樂觀鎖、悲觀鎖和自旋鎖
- 5.2 Synchronized
- 5.3 ReentrantLock
- 5.4 公平鎖和非公平鎖
- 5.3.1 說說ReentrantLock的實現原理,以及ReentrantLock的核心源碼是如何實現的?
- 5.5 鎖優化和升級
- 6.多線程的上下文切換
- 7.死鎖的產生和解決
- 8.J.U.C(java.util.concurrent)
- 0.簡化版(快速復習用)
- 9.鎖優化
- 10.Java 內存模型(JMM)
- 11.ThreadLocal詳解
- 12 CAS
- 13.AQS
- 0.ArrayBlockingQueue和LinkedBlockingQueue的實現原理
- 1.DelayQueue的實現原理
- 14.Thread.join()實現原理
- 15.PriorityQueue 的特性和原理
- 16.CyclicBarrier的實際使用場景
- 五.Java I/O NIO
- 1.I/O模型簡述
- 2.Java NIO之緩沖區
- 3.JAVA NIO之文件通道
- 4.Java NIO之套接字通道
- 5.Java NIO之選擇器
- 6.基于 Java NIO 實現簡單的 HTTP 服務器
- 7.BIO-NIO-AIO
- 8.netty(一)
- 9.NIO面試題
- 六.Java設計模式
- 1.單例模式
- 2.策略模式
- 3.模板方法
- 4.適配器模式
- 5.簡單工廠
- 6.門面模式
- 7.代理模式
- 七.數據結構和算法
- 1.什么是紅黑樹
- 2.二叉樹
- 2.1 二叉樹的前序、中序、后序遍歷
- 3.排序算法匯總
- 4.java實現鏈表及鏈表的重用操作
- 4.1算法題-鏈表反轉
- 5.圖的概述
- 6.常見的幾道字符串算法題
- 7.幾道常見的鏈表算法題
- 8.leetcode常見算法題1
- 9.LRU緩存策略
- 10.二進制及位運算
- 10.1.二進制和十進制轉換
- 10.2.位運算
- 11.常見鏈表算法題
- 12.算法好文推薦
- 13.跳表
- 八.Spring 全家桶
- 1.Spring IOC
- 2.Spring AOP
- 3.Spring 事務管理
- 4.SpringMVC 運行流程和手動實現
- 0.Spring 核心技術
- 5.spring如何解決循環依賴問題
- 6.springboot自動裝配原理
- 7.Spring中的循環依賴解決機制中,為什么要三級緩存,用二級緩存不夠嗎
- 8.beanFactory和factoryBean有什么區別
- 九.數據庫
- 1.mybatis
- 1.1 MyBatis-# 與 $ 區別以及 sql 預編譯
- Mybatis系列1-Configuration
- Mybatis系列2-SQL執行過程
- Mybatis系列3-之SqlSession
- Mybatis系列4-之Executor
- Mybatis系列5-StatementHandler
- Mybatis系列6-MappedStatement
- Mybatis系列7-參數設置揭秘(ParameterHandler)
- Mybatis系列8-緩存機制
- 2.淺談聚簇索引和非聚簇索引的區別
- 3.mysql 證明為什么用limit時,offset很大會影響性能
- 4.MySQL中的索引
- 5.數據庫索引2
- 6.面試題收集
- 7.MySQL行鎖、表鎖、間隙鎖詳解
- 8.數據庫MVCC詳解
- 9.一條SQL查詢語句是如何執行的
- 10.MySQL 的 crash-safe 原理解析
- 11.MySQL 性能優化神器 Explain 使用分析
- 12.mysql中,一條update語句執行的過程是怎么樣的?期間用到了mysql的哪些log,分別有什么作用
- 十.Redis
- 0.快速復習回顧Redis
- 1.通俗易懂的Redis數據結構基礎教程
- 2.分布式鎖(一)
- 3.分布式鎖(二)
- 4.延時隊列
- 5.位圖Bitmaps
- 6.Bitmaps(位圖)的使用
- 7.Scan
- 8.redis緩存雪崩、緩存擊穿、緩存穿透
- 9.Redis為什么是單線程、及高并發快的3大原因詳解
- 10.布隆過濾器你值得擁有的開發利器
- 11.Redis哨兵、復制、集群的設計原理與區別
- 12.redis的IO多路復用
- 13.相關redis面試題
- 14.redis集群
- 十一.中間件
- 1.RabbitMQ
- 1.1 RabbitMQ實戰,hello world
- 1.2 RabbitMQ 實戰,工作隊列
- 1.3 RabbitMQ 實戰, 發布訂閱
- 1.4 RabbitMQ 實戰,路由
- 1.5 RabbitMQ 實戰,主題
- 1.6 Spring AMQP 的 AMQP 抽象
- 1.7 Spring AMQP 實戰 – 整合 RabbitMQ 發送郵件
- 1.8 RabbitMQ 的消息持久化與 Spring AMQP 的實現剖析
- 1.9 RabbitMQ必備核心知識
- 2.RocketMQ 的幾個簡單問題與答案
- 2.Kafka
- 2.1 kafka 基礎概念和術語
- 2.2 Kafka的重平衡(Rebalance)
- 2.3.kafka日志機制
- 2.4 kafka是pull還是push的方式傳遞消息的?
- 2.5 Kafka的數據處理流程
- 2.6 Kafka的腦裂預防和處理機制
- 2.7 Kafka中partition副本的Leader選舉機制
- 2.8 如果Leader掛了的時候,follower沒來得及同步,是否會出現數據不一致
- 2.9 kafka的partition副本是否會出現腦裂情況
- 十二.Zookeeper
- 0.什么是Zookeeper(漫畫)
- 1.使用docker安裝Zookeeper偽集群
- 3.ZooKeeper-Plus
- 4.zk實現分布式鎖
- 5.ZooKeeper之Watcher機制
- 6.Zookeeper之選舉及數據一致性
- 十三.計算機網絡
- 1.進制轉換:二進制、八進制、十六進制、十進制之間的轉換
- 2.位運算
- 3.計算機網絡面試題匯總1
- 十四.Docker
- 100.面試題收集合集
- 1.美團面試常見問題總結
- 2.b站部分面試題
- 3.比心面試題
- 4.騰訊面試題
- 5.哈羅部分面試
- 6.筆記
- 十五.Storm
- 1.Storm和流處理簡介
- 2.Storm 核心概念詳解
- 3.Storm 單機版本環境搭建
- 4.Storm 集群環境搭建
- 5.Storm 編程模型詳解
- 6.Storm 項目三種打包方式對比分析
- 7.Storm 集成 Redis 詳解
- 8.Storm 集成 HDFS 和 HBase
- 9.Storm 集成 Kafka
- 十六.Elasticsearch
- 1.初識ElasticSearch
- 2.文檔基本CRUD、集群健康檢查
- 3.shard&replica
- 4.document核心元數據解析及ES的并發控制
- 5.document的批量操作及數據路由原理
- 6.倒排索引
- 十七.分布式相關
- 1.分布式事務解決方案一網打盡
- 2.關于xxx怎么保證高可用的問題
- 3.一致性hash原理與實現
- 4.微服務注冊中心 Nacos 比 Eureka的優勢
- 5.Raft 協議算法
- 6.為什么微服務架構中需要網關
- 0.CAP與BASE理論
- 十八.Dubbo
- 1.快速掌握Dubbo常規應用
- 2.Dubbo應用進階
- 3.Dubbo調用模塊詳解
- 4.Dubbo調用模塊源碼分析
- 6.Dubbo協議模塊