- [面試題]Java【基礎】
- [面試題]Java【虛擬機】
- [面試題]Java【并發】
- [面試題]Java【集合】
- [面試題]MySQL
- [面試題]Maven
- [面試題]Spring Boot
- [面試題]Spring Cloud
- [面試題]Spring MVC
- [面試題]Spring
- [面試題]MyBatis
- [面試題]Nginx
- [面試題]緩存
- [面試題]Redis
- [面試題]消息隊列
- [面試題]Kafka
- [面試題]RabbitMQ
- [面試題]MongoDB
- [面試題]Dubbo
- [面試題]Git
- [面試題]Jenkins
- [面試題]Linux
- [面試題]Netty
- [面試題]Zookeeper
- [面試題]計算機網絡
網絡體系結構
強烈推薦閱讀兩篇文章:
可以后續回過頭來看。
- 《計算機網絡體系結構綜述(上)》
- 《計算機網絡體系結構綜述(下)》
簡單一瞥:
- OSI 七層體系結構具有概念清楚、理論完整的特點,是一個理論上的國際標準,但卻不是事實上的國際標準。
- 具有簡單易用特點的 TCP/IP 四層體系結構則是事實上的標準。
- 需要指出的是,五層體系結構雖然綜合了 OSI 和 TCP/IP 的優點,但其只是為了學術學習研究而提出的,沒有具體的實際意義。
- 三者結構示意圖如下所示:原理體系結構 VS OS VS TCP/IP
簡述 OSI 七層體系結構
比較復雜,至少要說出有哪些層。
自上而下是:
- 應用層(數據):確定進程之間通信的性質以滿足用戶需要以及提供網絡與用戶應用
- 表示層(數據):主要解決用戶信息的語法表示問題,如加密解密
- 會話層(數據):提供包括訪問驗證和會話管理在內的建立和維護應用之間通信的機制,如服務器驗證用戶登錄便是由會話層完成的
- 傳輸層(段):實現網絡不同主機上用戶進程之間的數據通信,可靠
- 網絡層(包):提供邏輯地址(IP)、選路,數據從源端到目的端的
- 數據鏈路層(幀):將上層數據封裝成幀,用MAC地址訪問媒介,錯誤檢測與修正
- 物理層(比特流):設備之間比特流的傳輸,物理接口,電氣特性等
詳細可以看 《計算機網絡體系結構綜述(下)》 的 「二. OSI 七層體系結構簡述」 小節。
OSI 七層體系結構
簡述 TCP/IP 四層體系結構
比較復雜,至少要說出有哪些層。
自上而下是:
實際上,如果我們把一些 RPC 框架的分層套到 TCP/IP 四層體系結構,也是可以的。跳到 《精盡 Dubbo 面試題》 的 「Dubbo 框架的分層設計」 問題瞅瞅噢。
- 應用層
HTTP、TELNET、FTP、SMTP
- 傳輸層
TCP、UDP
- 網絡層
IP、ICMP
- 數據接口
PPP
詳細可以看 《計算機網絡體系結構綜述(下)》 的 「三. TCP/IP 四層體系結構」 小節。
知道各個層使用的是哪個數據交換設備?
這個問題,了解即可。
- 網關:應用層、傳輸層。
網關在傳輸層上以實現網絡互連,是最復雜的網絡互連設備,僅用于兩個高層協議不同的網絡互連。網關的結構也和路由器類似,不同的是互連層。網關既可以用于廣域網互連,也可以用于局域網互連。
- 【重點】路由器:網絡層
路由選擇、存儲轉發
- 【重點】交換機:數據鏈路層、網絡層
識別數據包中的 MAC 地址信息,根據 MAC 地址進行轉發,并將這些 MAC 地址與對應的端口記錄在自己內部的一個地址表中。
- 網橋:數據鏈路層
將兩個 LAN 連起來,根據 MAC 地址來轉發幀。
- 集線器(Hub):物理層
純硬件設備,主要用來連接計算機等網絡終端。
- 中繼器:物理層
在比特級別對網絡信號進行再生和重定時,從而使得它們能夠在網絡上傳輸更長的距離。
交換機是什么?
在計算機網絡系統中,交換機是針對共享工作模式的弱點而推出的。交換機擁有一條高帶寬的背部總線和內部交換矩陣。交換機的所有的端口都掛接在這條背部總線上,當控制電路收到數據包以后,處理端口會查找內存中的地址對照表以確定目的 MAC(網卡的硬件地址)的 NIC(網卡)掛接在哪個端口上,通過內部交換矩陣迅速將數據包傳送到目的端口。目的 MAC 若不存在,交換機才廣播到所有的端口,接收端口回應后交換機會“學習”新的地址,并把它添加入內部地址表中。
交換機工作于 OSI 參考模型的第二層,即數據鏈路層。交換機內部的 CPU 會在每個端口成功連接時,通過 ARP 協議學習它的 MAC 地址,保存成一張 ARP 表。在今后的通訊中,發往該 MAC 地址的數據包將僅送往其對應的端口,而不是所有的端口。因此,交換機可用于劃分數據鏈路層廣播,即沖突域;但它不能劃分網絡層廣播,即廣播域。
路由器是什么?
路由器(Router),是一種計算機網絡設備,提供了路由與轉發兩種重要機制,可以決定數據包從來源端到目的端所經過的路由路徑(host 到 host 之間的傳輸路徑),這個過程稱為路由;將路由器輸入端的數據包移送至適當的路由器輸出端(在路由器內部進行),這稱為轉發。所以,路由器的一個作用是連通不同的網絡,另一個作用是選擇信息傳送的線路。
路由工作在 OSI 模型的第三層 —— 即網絡層,例如 IP 協議。當然,這也是路由器與交換器的差別,路由器是屬于 OSI 第三層的產品,交換器是 OSI 第二層的產品(這里特指二層交換機)。
常見的路由選擇協議,以及它們的區別?
常見的路由選擇協議有:RIP 協議、OSPF 協議。
- RIP 協議:底層是貝爾曼福特算法,它選擇路由的度量標準(metric)是跳數,最大跳數是 15 跳。如果大于 15 跳,它就會丟棄數據包。
- OSPF 協議:底層是迪杰斯特拉算法,是鏈路狀態路由選擇協議,它選擇路由的度量標準是帶寬,延遲。
什么是網關設備?
這個我們就不在本文中多寫,感興趣的胖友,可以看看 《維基百科 —— 網關》 文章。
詳細說明 Keepalived 的故障切換工作原理?
這種故障切換,是通過 VRRP 協議來實現的。
- 主節點會按一定的時間間隔發送心跳信息的廣播包,告訴備節點自己的存活狀態信息。
- 當主節點發生故障時,備節點在一段時間內就收到廣播包,從而判斷主節點出現故障,因此會調用自身的接管程序來接管主節點的 IP 資源及服務。
- 當主節點恢復時,備節點會主動釋放資源,恢復到接管前的狀態,從而來實現主備故障切換
例如,MySQL 基于 Keepalived 實現高可用。詳細的,可以看看 《Keepalived + MySQL實現高可用》 。
IP
IP 地址的分類?
IP 地址是指互聯網協議地址,是 IP 協議提供的一種統一的地址格式,它為互聯網上的每一個網絡和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差異。
IP 地址編址方案將IP地址空間劃分為 A、B、C、D、E 五類,其中 A、B、C 是基本類,D、E 類作為多播和保留使用,為特殊地址。
每個 IP 地址包括兩個標識碼(ID),即網絡 ID 和主機 ID 。同一個物理網絡上的所有主機都使用同一個網絡 ID ,網絡上的一個主機(包括網絡上工作站,服務器和路由器等)有一個主機 ID 與其對應。A~E 類地址的特點如下:
五類互聯網地址
- A 類地址:以 0 開頭,第一個字節范圍:0~127 。
- B 類地址:以 10 開頭,第一個字節范圍:128~191 。
- C 類地址:以 110 開頭,第一個字節范圍:192~223。
- D 類地址:以 1110 開頭,第一個字節范圍:224~239 。
- E 類地址:以 1111 開頭,保留地址。
詳細的,可以看看 《IP 地址分類(A類 B類 C類 D類 E類)》 文章。
IP 地址與物理地址的區別?
- 物理地址(MAC 地址),是數據鏈路層和物理層使用的地址。
- IP 地址是網絡層和以上各層使用的地址,是一種邏輯地址。
- 其中 ARP 協議用于 IP 地址與物理地址的對應。
詳細的,可以看看 《即生瑜,何生亮 —— MAC 地址與 IP 地址》 文章。
網絡層的 ARP 協議工作原理?
網絡層的 ARP 協議完成了 IP 地址與物理地址的映射。
-
首先,每臺主機都會在自己的 ARP 緩沖區中建立一個 ARP 列表,以表示 IP 地址和 MAC 地址的對應關系。
-
當源主機需要將一個數據包要發送到目的主機時,會首先檢查自己 ARP 列表中是否存在該 IP 地址對應的 MAC 地址:
-
如果有,就直接將數據包發送到這個 MAC 地址。
-
如果沒有,就向本地網段發起一個ARP請求的廣播包,查詢此目的主機對應的 MAC 地址。此 ARP 請求數據包里包括源主機的 IP 地址、硬件地址、以及目的主機的 IP 地址。網絡中所有的主機收到這個 ARP 請求后,會檢查數據包中的目的 IP 是否和自己的 I P地址一致。
-
如果不相同,就忽略此數據包。
-
如果相同,該主機首先將發送端的 MAC 地址和 IP 地址添加到自己的 ARP 列表中(如果 ARP 表中已經存在該 IP 的信息,則將其覆蓋),然后給源主機發送一個 ARP 響應數據包,告訴對方自己是它需要查找的 MAC 地址。
- 源主機收到這個 ARP 響應數據包后,將得到的目的主機的 IP 地址和 MAC 地址添加到自己的 ARP 列表中,并利用此信息開始數據的傳輸。
- 如果源主機一直沒有收到 ARP 響應數據包,表示 ARP 查詢失敗。
-
-
注意,在 OSI 模型中 ARP 協議屬于鏈路層;而在 TCP/IP 模型中,ARP 協議屬于網絡層。
如何劃分子網、超網?
如何劃分子網?
可選了解。
劃分子網(變長子網掩碼 VLSM):劃分子網的方法是從網絡的主機號借用若干位作為子網號 subnet-id ,與此同時主機號也減少相應位數(總位數 32 位不變)。
由此兩級 IP 地址可變為三級 IP 地址:IP地址 ::= {<網絡號>,<子網號>,<主機號>} ,劃分子網只是把 IP 地址的主機號這部分進行再劃分,并不改變 IP 地址原來的網絡號。
如何劃分超網?
可選了解。
構造超網(無分類編址 CIDR):CIDR 消除了傳統的 A 類、B 類和 C 類地址以及劃分子網的概念,把 32 位的 IP 地址劃分為兩個部分。
例如:128.14.35.7/20 是某個 CIDR 地址塊中的一個地址,其前 20 位是網絡前綴(用下劃線表示的部分),后面的 12 位為主機號
子網掩碼的作用?
子網掩碼只有一個作用,就是將某個 IP 地址劃分成網絡地址和主機地址兩部分。
用于子網掩碼的位數,決定于可能的子網數目和每個子網的主機數目。
什么是單播、組播(多播)、廣播、任播?
這個問題,一般面試應該不問,主要是為了大家擴充下知識面吧。
- 單播(unicast): 是指封包在計算機網絡的傳輸中,目的地址為單一目標的一種傳輸方式。它是現今網絡應用最為廣泛,通常所使用的網絡協議或服務大多采用單播傳輸,例如一切基于TCP的協議。
- 組播(multicast): 也叫多播, 多點廣播或群播。 指把信息同時傳遞給一組目的地址。它使用策略是最高效的,因為消息在每條網絡鏈路上只需傳遞一次,而且只有在鏈路分叉的時候,消息才會被復制。
- 廣播(broadcast):是指封包在計算機網絡中傳輸時,目的地址為網絡中所有設備的一種傳輸方式。實際上,這里所說的“所有設備”也是限定在一個范圍之中,稱為“廣播域”。
- 任播(anycast):是一種網絡尋址和路由的策略,使得資料可以根據路由拓樸來決定送到“最近”或“最好”的目的地。
感興趣的胖友,可以詳細看 《單播,組播(多播),廣播以及任播》 文章。
區別 IPv4 和 IPv6 ?
- 我們大多數人使用的是第二代互聯網 IPv4 技術,它的最大問題是網絡地址資源有限,從理論上講能編址 1600 萬個網絡、鏈接 40 億臺主機。而根據相關數據,全球 IPv4 的 IP 地址已經即將用完。
- 而 IPv6 是作為 IETF 設計的用于替代現行版本 IP 協議(IPv4)的下一代 IP 協議,其 IPV6 地址長度為 12 8位,地址空間增大了 2^98 次方倍,幾乎可以說是用之不竭的。所以隨著 IPv4 不足,支持 IPv6 的網絡勢必會增長。
ICMP
這個小節,可以快速看。因為,面試不一定問的很多。
ICMP 協議的主要功能?
用于在 IP 主機、路由器之間傳遞控制消息。
簡述一下 ping 的原理?
一般在網絡不通的時候,大家會用 ping 測一下網絡是否通暢。
ping 是基于 ICMP 協議工作的。ICMP 全稱 Internet Control Message Protocol ,就是互聯網控制報文協議。這里的關鍵詞是“控制”,那具體是怎么控制的呢? 網絡包在異常負責的網絡環境中傳輸時,會遇到各種問題,當遇到問題時,要傳出消息,報告情況,這樣才能調整傳輸策略。
ICMP 報文是封裝在 IP 包里面的。因為傳輸指令的時候,肯定需要源地址和目標地址。如下圖:ICMP 報文
什么是 Traceroute ?
Traceroute 是構建在 ICMP 協議之上的應用。
Traceroute ,是用來偵測主機到目的主機之間所經路由情況的重要工具,也是最便利的工具。
前面說到,盡管 ping 工具也可以進行偵測,但是,因為 IP 頭的限制,ping 不能完全的記錄下所經過的路由器。所以Traceroute 正好就填補了這個缺憾。
Traceroute 的原理是非常非常的有意思。
它受到目的主機的 IP 后,首先給目的主機發送一個 TTL=1(還記得 TTL 是什么嗎?)的 UDP(后面就知道 UDP是什么了)數據包,而經過的第一個路由器收到這個數據包以后,就自動把 TTL 減1,而 TTL 變為 0 以后,路由器就把這個包給拋棄了,并同時產生 一個主機不可達的 ICMP 數據報給主機。主機收到這個數據報以后再發一個 TTL=2 的 UDP 數據報給目的主機,然后刺激第二個路由器給主機發 ICMP 數據 報。如此往復直到到達目的主機。這樣,traceroute 就拿到了所有的路由器 IP 。從而避開了 IP 頭只能記錄有限路由 IP 的問題。
有人要問,我怎么知道 UDP 到沒到達目的主機呢?
這就涉及一個技巧的問題,TCP 和 UDP 協議有一個端口號定義,而普通的網絡程序只監控少數的幾個號碼較小的端口,比如說 80、23 等等。而 traceroute 發送的是端口號 >30000(真變態) 的 UDP 包,所以到達目的主機的時候,目的主機只能發送一個端口不可達的 ICMP 數據報給主機。主機接到這個報告以后就知道,目標主機到了。
很多情況下,在我們 ping 不通目標地址時,會嘗試使用 traceroute 命令,看看是否在中間哪個 IP 無法訪問。
TCP
TCP 是什么?
TCP(Transmission Control Protocol),傳輸控制協議,是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。主要特點如下:
- TCP 是面向連接的。
就好像打電話一樣,通話前需要先撥號建立連接,通話結束后要掛機釋放連接
- 每一條 TCP 連接只能有兩個端點,每一條TCP連接只能是點對點的(一對一)。
- TCP 提供可靠交付的服務。通過TCP連接傳送的數據,無差錯、不丟失、不重復、并且按序到達。
- TCP 提供全雙工通信。TCP 允許通信雙方的應用進程在任何時候都能發送數據。TCP 連接的兩端都設有發送緩存和接收緩存,用來臨時存放雙方通信的數據。
- 面向字節流。
TCP 中的“流”(Stream),指的是流入進程或從進程流出的字節序列。“面向字節流”的含義是:雖然應用程序和 TCP 的交互是一次一個數據塊(大小不等),但 TCP 把應用程序交下來的數據僅僅看成是一連串的無結構的字節流。
TCP 對應的應用層協議?
-
FTP :定義了文件傳輸協議,使用 21 端口。常說某某計算機開了 FTP 服務便是啟動了文件傳輸服務。下載文件,上傳主頁,都要用到 FTP 服務。
-
Telnet :它是一種用于遠程登陸的端口,用戶可以以自己的身份遠程連接到計算機上,通過這種端口可以提供一種基于 DOS 模式下的通信服務。如以前的 BBS 是純字符界面的,支持 BBS 的服務器將 23 端口打開,對外提供服務。
-
郵箱
- SMTP :定義了簡單郵件傳送協議,現在很多郵件服務器都用的是這個協議,用于發送郵件。如常見的免費郵件服務中用的就是這個郵件服務端口,所以在電子郵件設置-中常看到有這么 SMTP 端口設置這個欄,服務器開放的是 25 號端口。
- POP3 :它是和 SMTP 對應,POP3 用于接收郵件。通常情況下,POP3 協議所用的是 110 端口。也是說,只要你有相應的使用 POP3 協議的程序(例如 Foxmail 或 Outlook),就可以不以 Web 方式登陸進郵箱界面,直接用郵件程序就可以收到郵件(如是 163 郵箱就沒有必要先進入網易網站,再進入自己的郵箱來收信)。
-
HTTP :從 Web 服務器傳輸超文本到本地瀏覽器的傳送協議。
TCP 頭部是怎么樣的?
- 《通俗大白話來理解 TCP 協議的三次握手和四次分手》 的 「TCP頭部」 小節。
- 《TCP 協議的學習 (二)TCP 頭部信息》
【重要】什么是 TCP 三次握手?
三次握手,簡單來說,就是:
TCP 三次握手的漫畫
- 發送方:我要和你建立鏈接?
- 接收方:你真的要和我建立鏈接么?
- 發送方:我真的要和你建立鏈接,成功。
詳細來說,步驟如下:
TCP 三次握手的干貨
-
第一次握手:Client 將標志位 SYN=1 ,隨機產生一個值 seq=J ,并將該數據包發送給 Server 。此時,Client 進入SYN_SENT 狀態,等待 Server 確認。
-
第二次握手:Server 收到數據包后由標志位 SYN=1 知道Client請求建立連接,Server 將標志位 SYN 和 ACK 都置為 1 ,ack=J+1,隨機產生一個值 seq=K ,并將該數據包發送給 Client 以確認連接請求,Server 進入 SYN_RCVD 狀態。此時,Server 進入 SYC_RCVD 狀態。
-
第三次握手:Client 收到確認后,檢查 ack 是否為 J+1 ,ACK 是否為 1 。
- 如果正確,則將標志位 ACK 置為 1 ,ack=K+1 ,并將該數據包發送給 Server 。此時,Client 進入 ESTABLISHED 狀態。
- Server 檢查 ack 是否為 K+1 ,ACK 是否為 1 ,如果正確則連接建立成功。此時 Server 進入 ESTABLISHED 狀態,完成三次握手,隨后 Client 與 Server 之間可以開始傳輸數據了。
-
仔細看來,Client 會發起兩次數據包,分別是 SYNC 和 ACK ;Server 會發起一次數據包,包含 SYNC 和 ACK 。也就是說,三次握手的過程中,Client 和 Server 互相做了一次 SYNC 和 ACK 。
為什么 TCP 連接需要三次握手,兩次不可以么,為什么?
為了防止已失效的連接請求報文突然又傳送到了服務端,因而產生錯誤。
客戶端發出的連接請求報文并未丟失,而是在某個網絡節點長時間滯留了,以致延誤到鏈接釋放以后的某個時間才到達 Server 。若不采用“三次握手”,那么只要 Server 發出確認數據包,新的連接就建立了。由于 Client 此時并未發出建立連接的請求,所以其不會理睬 Server 的確認,也不與 Server 通信;而這時 Server 一直在等待 Client 的請求,這樣 Server 就白白浪費了一定的資源。若采用“三次握手”,在這種情況下,由于 Server 端沒有收到來自客戶端的確認,則就會知道 Client 并沒有要求建立請求,就不會建立連接。
在 《通俗大白話來理解 TCP 協議的三次握手和四次揮手》 中,搜 “為什么要三次握手” 關鍵字,也有非常好的解答。
- 這就很明白了,防止了服務器端的一直等待而浪費資源。
客戶端不斷進行請求鏈接會怎樣?
服務器端準備為每個請求創建一個鏈接,并向其發送確認報文,然后等待客戶端進行確認后創建。如果此時客戶端一直不確認,會造成 SYN 攻擊,即:
SYN 攻擊,英文為 SYN Flood ,是一種典型的 DoS/DDoS 攻擊。
- 1、客戶端向服務端發送請求連接數據包。
- 2、服務端向客戶端發送確認數據包。
- 3、客戶端不向服務端發送確認數據包,服務器一直等待來自客戶端的確認。
這是這一步!!!
🚀 如何檢測 SYN 攻擊?檢測 SYN 攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源 IP 地址是隨機的,基本上可以斷定這是一次 SYN 攻擊。在 Linux/Unix 上可以使用系統自帶的 netstat 命令來檢測 SYN 攻擊。
🚀 怎么解決 SYN 攻擊呢?答案是只能預防,沒有徹底根治的辦法,除非不使用 TCP 。方式如下:
- 1、限制同時打開 SYN 半鏈接的數目
是不是很像我們常用的“限流”。
- 2、縮短 SYN 半鏈接的 Timeout 時間
是不是很像我們常用的“超時”。
- 3、關閉不必要的服務。
醬紫,這個服務就不會被 SYN 攻擊連接。
- 4、增加最大半連接數。
- 5、過濾網關防護。
- 6、SYN cookie 技術。
有一點點重新“設計” TCP 的味道,或者可以理解成對 TCP 的增強。
【重要】什么是 TCP 四次揮手?
四次揮手,簡單來說,就是:
- 發送方:我要和你斷開連接!
- 接收方:好的,斷吧。
- 接收方:我也要和你斷開連接!
- 發送方:好的,斷吧。
詳細來說,步驟如下:
TCP 四次揮手的干貨
如下使用 Client 和 Server 的方式,僅僅是為了方便,也是可以從 Server 向 Client 發起。
- 第一次揮手:Client 發送一個 FIN=M ,用來關閉 Client 到 Server 的數據傳送。此時,Client 進入 FIN_WAIT_1 狀態。
- 第二次揮手,Server 收到 FIN 后,發送一個 ACK 給 Client ,確認序號為 M+1(與 SYN 相同,一個 FIN 占用一個序號)。此時,Server 進入 CLOSE_WAIT 狀態。注意,TCP 鏈接處于半關閉狀態,即客戶端已經沒有要發送的數據了,但服務端若發送數據,則客戶端仍要接收。
- 第三次揮手,Server 發送一個 FIN=N ,用來關閉 Server 到 Client 的數據傳送。此時 Server 進入 LAST_ACK 狀態。
- 第四次揮手,Client 收到 FIN 后,此時 Client 進入 TIME_WAIT 狀態。接著,Client 發送一個 ACK 給 Server ,確認序號為 N+1 。Server 接收到后,此時 Server 進入 CLOSED 狀態,完成四次揮手。
為什么要四次揮手?
TCP 協議是一種面向連接的、可靠的、基于字節流的運輸層通信協議。TCP 是全雙工模式,這就意味著:
- 當主機 1 發出
FIN 報文段時,只是表示主機 1 已經沒有數據要發送了,主機 1 告訴主機 2 ,它的數據已經全部發送完畢了;但是,這個時候主機 1 還是可以接受來自主機 2 的數據;當主機 2 返回 ACK 報文段時,表示它已經知道主機 1 沒有數據發送了,但是主機 2 還是可以發送數據到主機 1 的。
因為主機 2 此時可能還有數據想要發送給主機 1 ,所以揮手不能像握手只有三次,而是多了那么“一次”!
- 當主機 2 也發送了
FIN 報文段時,這個時候就表示主機 2 也沒有數據要發送了,就會告訴主機 1 ,我也沒有數據要發送了,之后彼此就會愉快的中斷這次 TCP 連接。
我們把四次揮手,理解成一次和平的揮手~
如果要正確的理解四次的原理,就需要了解四次揮手過程中的狀態變化。
主動方=發送方;被動方=接收方。狀態前面的(主動方)(被動方),表示該狀態屬于誰。
-
(主動方)FIN_WAIT_1 :這個狀態要好好解釋一下,其實 FIN_WAIT_1 和 FIN_WAIT_2 狀態的真正含義都是表示等待對方的 FIN 報文。而這兩種狀態的區別是:
- FIN_WAIT_1 狀態實際上是當 Socket 在 ESTABLISHED 狀態時,它想主動關閉連接,向對方發送了 FIN 報文,此時該 Socket 即進入到 FIN_WAIT_1 狀態。
- 而當對方回應 ACK 報文后,則進入到 FIN_WAIT_2 狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK 報文。所以, FIN_WAIT_1 狀態一般是比較難見到的,而 FIN_WAIT_2 狀態還有時常常可以用 netstat 看到。
-
(主動方)FIN_WAIT_2 :上面已經詳細解釋了這種狀態,實際上 FIN_WAIT_2 狀態下的 Socket,表示半連接,也即有一方要求 close 連接,但另外還告訴對方,我暫時還有點數據需要傳送給你(ACK 信息),稍后再關閉連接。
-
(被動方)CLOSE_WAIT :這種狀態的含義其實是表示在等待關閉。怎么理解呢?當對方 close 一個 Socket 后發送 FIN 報文給自己,你系統毫無疑問地會回應一個 ACK 報文給對方,此時則進入到 CLOSE_WAIT 狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那么你也就可以 close 這個 Socket ,發送 FIN 報文給對方,也即關閉連接。所以你在 CLOSE_WAIT 狀態下,需要完成的事情是等待你去關閉連接。
-
(被動方)LAST_ACK :這個狀態還是比較容易好理解的,它是被動關閉一方在發送 FIN 報文后,最后等待對方的 ACK 報文。當收到 ACK 報文后,也即可以進入到 CLOSED 可用狀態了。
-
(主動方)TIME_WAIT :表示收到了對方的
FIN 報文,并發送出了 ACK 報文,就等 2MSL 后即可回到 CLOSED 可用狀態了。如果 FIN_WAIT_1 狀態下,收到了對方同時帶 FIN 標志和 ACK 標志的報文時,可以直接進入到 TIME_WAIT 狀態,而無須經過 FIN_WAIT_2 狀態。
為何一定要等 2MSL ?如果不等,釋放的端口可能會重連剛斷開的服務器端口,這樣依然存活在網絡里的老的 TCP 報文可能與新 TCP 連接報文沖突,造成數據沖突,為避免此種情況,需要耐心等待網絡老的 TCP 連接的活躍報文全部死翹翹,2MSL 時間可以滿足這個需求(盡管非常保守)!更多,可以看看知乎 《為什么 TCP 4 次揮手時等待為 2MSL?》 的討論。
- CLOSED :表示連接中斷。
另外,關于 TIME_WAIT 和 CLOSE_WAIT 狀態的區別,胖友可以在細看下 《TIME_WAIT 和 CLOSE_WAIT 狀態區別》 。
【重要】TCP 數據如何傳輸?
建立連接后,兩臺主機就可以相互傳輸數據了。如下圖所示:TCP 套接字的數據交換過程
-
上圖給出了主機 A 分 2 次(分 2 個數據包)向主機 B 傳遞 200 字節的過程。
-
首先,主機 A 通過 1 個數據包發送 100 個字節的數據,數據包的 Seq 號設置為 1200 。主機 B 為了確認這一點,向主機 A 發送 ACK 包,并將 Ack 號設置為 1301 。
-
為了保證數據準確到達,目標機器在收到數據包(包括 SYN 包、FIN 包、普通數據包等)包后必須立即回傳 ACK 包,這樣發送方才能確認數據傳輸成功。
-
此時 Ack 號為 1301 而不是 1201,原因在于 Ack 號的增量為傳輸的數據字節數。假設每次 Ack 號不加傳輸的字節數,這樣雖然可以確認數據包的傳輸,但無法明確 100 字節全部正確傳遞還是丟失了一部分,比如只傳遞了 80 字節。因此按如下的公式確認 Ack 號:Ack 號 = Seq 號 + 傳遞的字節數 + 1 。
- 與三次握手協議相同,最后加 1 是為了告訴對方要傳遞的 Seq 號。
-
OK,讓我們重新來看下 TCP 的整個過程。如下圖所示:TCP 過程
TCP 數據傳輸丟失怎么辦?
這個問題,也可以改成提問,什么是 TCP 重傳。
因為各種原因,TCP 數據包可能存在丟失的情況,TCP 會進行數據重傳。如下圖所示:
TCP套接字數據傳輸過程中發生錯誤
- 上圖表示通過 Seq 1301 數據包向主機 B 傳遞 100 字節的數據,但中間發生了錯誤,主機 B 未收到。經過一段時間后,主機 A 仍未收到對于 Seq 1301 的 ACK 確認,因此嘗試重傳數據。為了完成數據包的重傳,TCP 套接字每次發送數據包時都會啟動定時器,如果在一定時間內沒有收到目標機器傳回的 ACK 包,那么定時器超時,數據包會重傳。上圖演示的是數據包丟失的情況,也會有 ACK 包丟失的情況,一樣會重傳。
- 重傳超時時間(RTO,Retransmission Time Out)
這個值太大了會導致不必要的等待,太小會導致不必要的重傳,理論上最好是網絡 RTT 時間,但又受制于網絡距離與瞬態時延變化,所以實際上使用自適應的動態算法(例如 Jacobson 算法和 Karn 算法等)來確定超時時間。往返時間(RTT,Round-Trip Time)表示從發送端發送數據開始,到發送端收到來自接收端的 ACK 確認包(接收端收到數據后便立即確認),總共經歷的時延。
- 重傳次數
TCP 數據包重傳次數,根據系統設置的不同而有所區別。有些系統,一個數據包只會被重傳 3 次,如果重傳 3 次后還未收到該數據包的 ACK 確認,就不再嘗試重傳。但有些要求很高的業務系統,會不斷地重傳丟失的數據包,以盡最大可能保證業務數據的正常交互。最后需要說明的是,發送端只有在收到對方的 ACK 確認包后,才會清空輸出緩沖區中的數據。
ps:TCP 數據傳輸的過程,和 MQ Broker 投遞消息給 Consumer 是一樣的,只有在 Consumer Ack 確認消息已經消費,該消息才不會再被投遞給 Consumer 。
另外,也推薦閱讀 《網絡基本功(九):細說TCP重傳》 。
【重要】什么是 TCP 滑動窗口?
在看 TCP 滑動窗口的概念之前,我們先來看看它出現的背景?
將 TCP 與 UDP 這樣的簡單傳輸協議區分開來的是,它傳輸數據的質量。TCP 對于發送數據進行跟蹤,這種數據管理需要協議有以下兩大關鍵功能:可靠性:保證數據確實到達目的地。如果未到達,能夠發現并重傳。數據流控:管理數據的發送速率,以使接收設備不致于過載。要完成這些任務,整個協議操作是圍繞滑動窗口 + 確認機制來進行的。因此,理解了滑動窗口,也就是理解了 TCP 。
那么,到底什么是 TCP 滑動窗口呢?
滑動窗口協議,是傳輸層進行流控的一種措施,接收方通過通告發送方自己的窗口大小,從而控制發送方的發送速度,從而達到防止發送方發送速度過快而導致自己被淹沒的目的。TCP 的滑動窗口解決了端到端的流量控制問題,允許接受方對傳輸進行限制,直到它擁有足夠的緩沖空間來容納更多的數據。
可能這么描述之后,胖友會有點懵逼,那么建議看下面三篇文章,耐心~
- 《TCP 滑動窗口控制流量的原理》
比較易懂的一篇文章。
- 《網絡基本功(八):細說 TCP 滑動窗口》
更為詳細的一篇文章。
- 《TCP 協議的滑動窗口具體是怎樣控制流量的?》
知乎上的討論,重點看「wuxinliulei」和「安靜的木小昊」的回答。特別是后者的,回答很生動形象。
TCP 協議如何來保證傳輸的可靠性?
TCP 提供一種面向連接的、可靠的字節流服務。其中,面向連接意味著兩個使用 TCP 的應用(通常是一個客戶和一個服務器)在彼此交換數據之前必須先建立一個 TCP 連接。
- 在一個 TCP 連接中,僅有兩方進行彼此通信。
- 而字節流服務意味著兩個應用程序通過 TCP 鏈接交換 8bit 字節構成的字節流,TCP 不在字節流中插入記錄標識符。
對于可靠性,TCP 通過以下方式進行保證:
- 數據包校驗:目的是檢測數據在傳輸過程中的任何變化,若校驗出包有錯,則丟棄報文段并且不給出響應,這時 TCP 發送數據端超時后會重發數據。
- 對失序數據包重排序:既然 TCP 報文段作為 IP 數據報來傳輸,而 IP 數據報的到達可能會失序,因此 TC P報文段的到達也可能會失序。TCP 將對失序數據進行重新排序,然后才交給應用層。
- 丟棄重復數據:對于重復數據,能夠丟棄重復數據。
- 應答機制:當 TCP 收到發自 TCP 連接另一端的數據,它將發送一個確認。這個確認不是立即發送,通常將推遲幾分之一秒。
- 超時重發:當 TCP 發出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發這個報文段。
- 流量控制:TCP 連接的每一方都有固定大小的緩沖空間。TCP 的接收端只允許另一端發送接收端緩沖區所能接納的數據,這可以防止較快主機致使較慢主機的緩沖區溢出,這就是流量控制。TCP 使用的流量控制協議是可變大小的滑動窗口協議。
什么是 TCP 擁堵?
計算機網絡中的帶寬、交換結點中的緩存及處理機等都是網絡的資源。在某段時間,若對網絡中某一資源的需求超過了該資源所能提供的可用部分,網絡的性能就會變壞,這種情況就叫做擁塞。
怎么解決 TCP 擁堵?
通過擁塞控制來解決。擁堵控制,就是防止過多的數據注入網絡中,這樣可以使網絡中的路由器或鏈路不致過載。注意,擁塞控制和流量控制不同,前者是一個全局性的過程,而后者指點對點通信量的控制。
擁塞控制的方法主要有以下四種:
- 1、慢開始。
- 2、擁塞避免。
- 3、快重傳。
- 4、快恢復。
1)慢開始
不要一開始就發送大量的數據,先探測一下網絡的擁塞程度,也就是說由小到大逐漸增加擁塞窗口的大小。
2)擁塞避免
擁塞避免算法,讓擁塞窗口緩慢增長,即每經過一個往返時間 RTT 就把發送方的擁塞窗口 cwnd 加 1 ,而不是加倍,這樣擁塞窗口按線性規律緩慢增長。
慢開始和擁塞避免算法的實現舉例
3)快重傳
快重傳,要求接收方在收到一個失序的報文段后就立即發出重復確認(為的是使發送方及早知道有報文段沒有到達對方),而不要等到自己發送數據時捎帶確認。
快重傳算法規定,發送方只要一連收到三個重復確認,就應當立即重傳對方尚未收到的報文段,而不必繼續等待設置的重傳計時器時間到期。
快重傳的示意圖
4)快恢復
快重傳配合使用的還有快恢復算法,當發送方連續收到三個重復確認時,就執行“乘法減小”算法,把 ssthresh 門限減半。
- 但是接下去并不執行慢開始算法:因為如果網絡出現擁塞的話就不會收到好幾個重復的確認,所以發送方現在認為網絡可能沒有出現擁塞。
- 所以此時不執行慢開始算法,而是將 cwnd 設置為 ssthresh 的大小,然后執行擁塞避免算法。
從連續收到三個重復的確認轉入擁堵避免
UDP
UDP 是什么?
UDP(User Data Protocol,用戶數據報協議),是與 TCP 相對應的協議。它是面向非連接的協議,它不與對方建立連接,而是直接就把數據包發送過去。
主要特點如下:
- UDP 是無連接的。
- UDP 使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持復雜的鏈接狀態(這里面有許多參數)。
- UDP 是面向報文的。
- UDP 沒有擁塞控制,因此網絡出現擁塞不會使源主機的發送速率降低。
對實時應用很有用,如 直播,實時視頻會議等
- UDP 支持一對一、一對多、多對一和多對多的交互通信。
- UDP 的首部開銷小,只有 8 個字節,比 TCP 的 20 個字節的首部要短。
UDP 對應的應用層協議?
- DNS :用于域名解析服務,將域名地址轉換為 IP 地址。DNS 用的是 53 號端口。
- SNMP :簡單網絡管理協議,使用 161 號端口,是用來管理網絡設備的。由于網絡設備很多,無連接的服務就體現出其優勢。
- TFTP(Trivial File Transfer Protocol):簡單文件傳輸協議,該協議在熟知端口 69 上使用 UDP 服務。
【重要】TCP 與 UDP 的區別
這個問題,上面在介紹 TCP 和 UDP 都提到了,就是做了整合哈。
TCP(Transmission Control Protocol)和 UDP(User Datagram Protocol) 協議屬于傳輸層協議,它們之間的區別包括:
TCP 與 UDP 的區別
- TCP 是面向連接的;UDP 是無連接的。
- TCP 是可靠的;UDP 是不可靠的。
- TCP 只支持點對點通信;UDP 支持一對一、一對多、多對一、多對多的通信模式。
- TCP 是面向字節流的;UDP 是面向報文的。
- TCP 有擁塞控制機制;UDP 沒有擁塞控制,適合媒體通信。
- TCP 首部開銷(20 個字節),比 UDP 的首部開銷(8 個字節)要大。
為什么 TCP 叫數據流模式? UDP 叫數據報模式?
所謂的“流模式”,是指TCP 發送端發送幾次數據和接收端接收幾次數據是沒有必然聯系的。
- 比如你通過 TCP 連接給另一端發送數據,你只調用了一次 write ,發送了 100 個字節,但是對方可以分 10 次收完,每次 10 個字節;你也可以調用 10 次 write ,每次 10 個字節,但是對方可以一次就收完。
- 原因:這是因為 TCP 是面向連接的,一個 Socket 中收到的數據都是由同一臺主機發出,且有序地到達,所以每次讀取多少數據都可以。
所謂的“數據報模式”,是指 UDP 發送端調用了幾次 write ,接收端必須用相同次數的 read 讀完。
- UDP 是基于報文的,在接收的時候,每次最多只能讀取一個報文,報文和報文是不會合并的,如果緩沖區小于報文長度,則多出的部分會被丟棄。
- 原因:這是因為 UDP 是無連接的,只要知道接收端的 IP 和端口,任何主機都可以向接收端發送數據。這時候,如果一次能讀取超過一個報文的數據,則會亂套。
UDP 報文的格式
- 16 位 * 4 = 64 位 = 8 字節。
DNS
DNS 是什么?
- 域名解析,www.xxx.com 轉換成 IP ,能夠使用戶更方便的訪問互聯網,而不用去記住能夠被機器直接讀取的 IP 數串。
- DNS 協議運行在 UDP 協議之上,使用端口號 53 。
主機解析域名的順序?
- 瀏覽器緩存
- 找本機的 hosts 文件
- 路由緩存
- 找 DNS 服務器(本地域名、頂級域名、根域名)
- 迭代查詢
- 遞歸查詢
DNS 使用什么協議?
參見 《DNS使用的是 TCP 協議還是 UDP 協議》 文章。
既使用 TCP 又使用 UDP 。
- 區域傳送時使用 TCP 協議。
輔域名服務器會定時(一般時 3 小時)向主域名服務器進行查詢以便了解數據是否有變動。如有變動,則會執行一次區域傳送,進行數據同步。區域傳送將使用 TCP 而不是 UDP ,因為數據同步傳送的數據量比一個請求和應答的數據量要多得多。TCP 是一種可靠的連接,保證了數據的準確性。
- 域名解析時使用 UDP 協議。
客戶端向 DNS 服務器查詢域名,一般返回的內容都不超過 512 字節,用 UDP 傳輸即可。UDP 報文的最大長度為 512 字節。不用經過 TCP 三次握手,這樣 DNS 服務器負載更低,響應更快。雖然從理論上說,客戶端也可以指定向 DNS 服務器查詢的時候使用 TCP ,但事實上,很多 DNS 服務器進行配置的時候,僅支持 UDP 查詢包。
HTTP
HTTP 是什么?
HTTP 協議,是 Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用于從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。
主要特點如下:
- 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法常用的有 GET、HEAD、POST 等等。每種方法規定了客戶與服務器聯系的類型不同。由于 HTTP 協議簡單,使得 HTTP 服務器的程序規模小,因而通信速度很快。
- 數據格式靈活:HTTP 允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type 加以標記。
- 無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
主要指的是不使用 Keep-Alive 機制的情況下。
- 無狀態:HTTP 協議是無狀態協議。無狀態,是指協議對于事務處理沒有記憶能力。無狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。
無狀態,所以更容易做服務的擴容,支撐更大的訪問量。
- 支持 B/S 及 C/S 模式。
另外,HTTP 協議已經不僅僅使用在瀏覽器上。在前后端分離的架構中,又或者微服務架構的內部通信中,HTTP 因為其數據格式的通用性,和語言無關,被大規模使用。
HTTP 基本格式
詳細的,可以看看 《貓哥網絡編程系列:詳解 BAT 面試題》 文章。
HTTP 請求格式
-
請求行:用來說明請求類型,要訪問的資源以及所使用的 HTTP 版本。
-
請求頭部:緊接著請求行(即第一行)之后的部分,用來說明服務器要使用的附加信息從第二行起為請求頭部。
- HOST ,將指出請求的目的地。
- User-Agent ,服務器端和客戶端腳本都能訪問它,它是瀏覽器類型檢測邏輯的重要基礎。該信息由你的瀏覽器來定義,并且在每個請求中自動發送等等
- …
-
空行:請求頭部后面的空行是必須的。
-
請求數據:也叫主體,可以添加任意的其他數據。
HTTP 響應格式
HTTP 響應格式
- 狀態行:由 HTTP 協議版本號、狀態碼、狀態消息三部分組成。
- 消息報頭:用來說明客戶端要使用的一些附加信息。
- 空行:消息報頭后面的空行是必須的。
- 響應正文:服務器返回給客戶端的文本信息。
URI 和 URL 的區別?
見 《URI 和 URL 的區別》 文章。
HTTP 協議包括哪些請求?
- GET: 對服務器資源的簡單請求。
- POST: 用于發送包含用戶提交數據的請求。
- HEAD:類似于 GET 請求,不過返回的響應中沒有具體內容,用于獲取報頭。
- PUT:傳說中請求文檔的一個版本。
- DELETE:發出一個刪除指定文檔的請求。
- TRACE:發送一個請求副本,以跟蹤其處理進程。
- OPTIONS:返回所有可用的方法,檢查服務器支持哪些方法。
- CONNECT:用于 SSL 隧道的基于代理的請求。
GET 和 POST 的區別?
請求方式 | 數據位置 | 明文密文 | 數據安全 | 長度限制 | 應用場景 |
---|---|---|---|---|---|
GET | HTTP 請求的 path 中 | 明文 | 不安全 | 長度較小,一般 2k | 查詢數據 |
POST | HTTP 請求 body 中 | 可明可密 | 安全 | 支持較大數據傳輸 | 修改數據 |
- GET 請求可被緩存;POST 請求不會被緩存。
- GET 請求可被收藏為書簽;POST 不能被收藏為書簽。
- 【非常有趣】參見
《99%的人理解錯 HTTP 中 GET 與 POST 的區別》
對于 GET 方式的請求,瀏覽器會把 HTTP header 和 data 一并發送出去,服務器響應 200(返回數據)。而對于 POST,瀏覽器先發送 header ,服務器響應 100 continue ,瀏覽器再發送 data ,服務器響應 200 ok(返回數據)。也就是說,GET 只需要汽車跑一趟就把貨送到了,而 POS T得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然后再回頭把貨送過去。ps:不過要注意,POST 具體發幾次,也和瀏覽器的實現有關系。例如:Firefox 只發一次。ps2:據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的 TCP 在驗證數據包完整性上,有非常大的優點。
HTTP 有哪些狀態碼?
-
1×× : 請求處理中,請求已被接受,正在處理
-
2×× : 請求成功,請求被成功處理
- 200 OK // 客戶端請求成功
-
3×× : 重定向,要完成請求必須進行進一步處理
- 301 Moved Permanently // 永久重定向,使用域名跳轉
- 302 Found // 臨時重定向,未登陸的用戶訪問用戶中心重定向到登錄頁面
-
4×× : 客戶端錯誤,請求不合法
- 400 Bad Request // 客戶端請求有語法錯誤,不能被服務器所理解
- 401 Unauthorized // 請求未經授權,這個狀態代碼必須和 WWW-Authenticate 報頭域一起使用
- 403 Forbidden // 服務器收到請求,但是拒絕提供服務
- 404 Not Found // 請求資源不存在,eg:輸入了錯誤的 URL
-
5×× : 服務器端錯誤,服務器不能處理合法請求
- 500 Internal Server Error // 服務器發生不可預期的錯誤
- 503 Server Unavailable // 服務器當前不能處理客戶端的請求,一段時間后可能恢復正常
完整的狀態碼列表,可以看看 《HTTP 狀態碼》 文章。
forward 和 redirect 的區別?
- 直接轉發方式(Forward),客戶端和瀏覽器只發出一次請求,Servlet、HTML、JSP 或其它信息資源,由第二個信息資源響應該請求,在請求對象 request 中,保存的對象對于每個信息資源是共享的。
- 間接轉發方式(Redirect),實際是兩次 HTTP 請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另外一個 URL 發出請求,從而達到轉發的目的。
詳細的,請看 《請求轉發(Forward)和重定向(Redirect)的區別》 。
HTTP 返回碼中 301 與 302 的區別?
301,302 都是 HTTP 狀態的編碼,都代表著某個 URL 發生了轉移,不同之處在于:
- 301 redirect: 301 代表永久性轉移(Permanently Moved)。
- 302 redirect: 302 代表暫時性轉移(Temporarily Moved)。
詳細的,請看 《HTTP 返回碼中 301 與 302 的區別》 文章。
HTTP、TCP、Socket 的關系是什么?
- TCP/IP 代表傳輸控制協議/網際協議,指的是一系列協議族。
- HTTP 本身就是一個協議,是從 Web 服務器傳輸超文本到本地瀏覽器的傳送協議。
- Socket 是 TCP/IP 網絡的 API ,其實就是一個門面模式,它把復雜的 TCP/IP 協議族隱藏在 Socket 接口后面。對用戶來說,一組簡單的接口就是全部,讓 Socket 去組織數據,以符合指定的協議。
綜上所述:
- 需要 IP 協議來連接網絡
- TCP 是一種允許我們安全傳輸數據的機制,使用 TCP 協議來傳輸數據的 HTTP 是 Web 服務器和客戶端使用的特殊協議。
- HTTP 基于 TCP 協議,所以可以使用 Socket 去建立一個 TCP 連接。
Cookies 和 Session 的區別
- Session 在服務器端,Cookie 在客戶端(瀏覽器)。
Session 默認被存在在服務器的一個文件里(不是內存)。
- Session 的運行依賴 sessionid ,而 sessionid 是存在 Cookie 中的,也就是說,如果瀏覽器禁用了 Cookie ,同時 session 也會失效。但是,可以通過其它方式實現,比如在 url 參數中傳遞 sessionid 。
- Session 可以放在文件、數據庫、或內存中都可以。
- 【關鍵】用戶驗證這種場合一般會用 Session 。
【重要】一次完整的 HTTP 請求所經歷的步驟
這里的客戶端,更多指的是瀏覽器。
- 1、DNS 解析(通過訪問的域名找出其 IP 地址,遞歸搜索)。
- 2、HTTP 請求,當輸入一個請求時,建立一個 Socket 連接發起 TCP的 3 次握手。
如果是 HTTPS 請求,會略微有不同。等到 HTTPS 小節,我們在來講。
- 3.1、客戶端向服務器發送請求命令(一般是 GET 或 POST 請求)。
這個是補充內容,面試一般不用回答。客戶端的網絡層不用關心應用層或者傳輸層的東西,主要做的是通過查找路由表確定如何到達服務器,期間可能經過多個路由器,這些都是由路由器來完成的工作,我不作過多的描述,無非就是通過查找路由表決定通過那個路徑到達服務器。客戶端的鏈路層,包通過鏈路層發送到路由器,通過鄰居協議查找給定 IP 地址的 MAC 地址,然后發送 ARP 請求查找目的地址,如果得到回應后就可以使用 ARP 的請求應答交換的 IP 數據包現在就可以傳輸了,然后發送 IP 數據包到達服務器的地址。
- 3.2、客戶端發送請求頭信息和數據。
- 4.1、服務器發送應答頭信息。
- 4.2、服務器向客戶端發送數據。
- 5、服務器關閉 TCP 連接(4次揮手)。
這里是否關閉 TCP 連接,也根據 HTTP Keep-Alive 機制有關。同時,客戶端也可以主動發起關閉 TCP 連接。
- 6、客戶端根據返回的 HTML、CSS、JS 進行渲染。
如下是《圖解HTTP》提供的圖片:HTTP 請求所經歷的步驟
HTTP1.0 和 HTTP1.1 有什么區別?
主要是如下 8 點:
- 1、可擴展性
- 2、緩存
- 3、帶寬優化
帶來了分塊傳輸 。可能的話,面試也會問。
- 【最重要】4、長連接
- 5、消息傳遞
- 6、Host 頭域
- 7、錯誤提示
- 8、內容協商
詳細的每一點的說明,可以看 《HTTP1.0 與 HTTP1.1 的區別》 文章,特別是第 4 點【長連接】。
HTTP1.1 支持長連接(PersistentConnection)和請求的流水線(Pipelining)。長連接(PersistentConnection):處理在一個 TCP 連接上可以傳送多個 HTTP 請求和響應,減少了建立和關閉連接的消耗和延遲。在 HTTP1.1中 默認開啟Connection:keep-alive ,一定程度上彌補了 HTTP1.0 每次請求都要創建連接的缺點。請求的流水線(Pipelining):HTTP1.1 還允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但服務器端必須按照接收到客戶端請求的先后順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容,這樣也顯著地減少了整個下載過程所需要的時間。推薦,在看看 《HTTP Keep-Alive 是什么?如何工作?》 文章。關于這一點,可能演變的問題有:HTTP 的長連接是什么意思?HTTP Keep-Alive 機制是什么?HTTP Keep-Alive 機制和 TCP Keep-Alive 有什么區別?
SPDY 是什么?
關于這個問題,了解就好。HTTP Working-Group 最終決定以 SPDY/2 為基礎,開發 HTTP/2 。
2012 年,Google 如一聲驚雷提出了 SPDY 的方案,優化了 HTTP1.X 的請求延遲,解決了 HTTP1.X 的安全性,具體如下:
- 1、降低延遲
針對 HTTP 高延遲的問題,SPDY 優雅的采取了多路復用(multiplexing)。多路復用通過多個請求 Stream 共享一個 Tcp連 接的方式,解決了 HOL blocking 的問題,降低了延遲同時提高了帶寬的利用率。
- 2、請求優先級(request prioritization)
多路復用帶來一個新的問題是,在連接共享的基礎之上有可能會導致關鍵請求被阻塞。SPDY 允許給每個 request 設置優先級,這樣重要的請求就會優先得到響應。比如瀏覽器加載首頁,首頁的 html 內容應該優先展示,之后才是各種靜態資源文件,腳本文件等加載,這樣可以保證用戶能第一時間看到網頁內容。
- 3、header 壓縮
前面提到 HTTP1.x 的 header 很多時候都是重復多余的。選擇合適的壓縮算法可以減小包的大小和數量。
- 4、基于 HTTPS 的加密協議傳輸
大大提高了傳輸數據的安全性。
- 5、服務端推送(server push)
采用了 SPDY 的網頁,例如我的網頁有一個 sytle.css 的請求,在客戶端收到 sytle.css 數據的同時,服務端會將 sytle.js 的文件推送給客戶端。當客戶端再次嘗試獲取 sytle.js 時就可以直接從緩存中獲取到,不用再發請求了。🙂 和我們理解的服務端推送,有點(非常)不一樣哈。
🚀 SPDY 構成圖如下:SPDY 構成圖
- SPDY 位于 HTTP 之下,TCP 和 SSL 之上,這樣可以輕松兼容老版本的 HTTP 協議(將 HTTP1.x 的內容封裝成一種新的 frame 格式),同時可以使用已有的 SSL 功能。
HTTPS
推薦先看下 《九個問題從入門到熟悉 HTTPS》 文章,寫的很有趣~
另外,也看看 《SSL/TLS 雙向認證(一) – SSL/TLS工作原理》 文章,寫的更技術向~
下面的面試題的答案,我們會基于上述文章來整理。
HTTPS 是什么?
HTTPS ,實際就是在 TCP 層與 HTTP 層之間加入了 SSL/TLS 來為上層的安全保駕護航,主要用到對稱加密、非對稱加密、證書,等技術進行客戶端與服務器的數據加密傳輸,最終達到保證整個通信的安全性。
一句話概括:HTTP + 加密 + 認證 + 完整性保護 = HTTPS 。
### 什么是 SSL 呢?什么是 TLS 呢?
官方定義,SSL 是安全套接層(secure sockets layer);TLS 是 SSL 的繼任者,叫傳輸層安全(transport layer security)。
它們存在的唯一目的就是保證上層通訊安全的一套機制。它的發展依次經歷了下面幾個時期,像手機軟件升級一樣,每次更新都添加或去除功能,比如引進新的加密算法,修改握手方式等。
- SSL1.0: 已廢除
- SSL2.0: RFC6176 ,已廢除
- SSL3.0: RFC6101 ,基本廢除
- TLS1.0: RFC2246 ,目前大都采用此種方式
- TLS1.1: RFC4346
- TLS1.2: RFC5246 ,沒有廣泛使用
- TLS1.3: IETF 正在醞釀中
為了下面描述方便,統一先叫 SSL 。
### SSL/TLS 協議作用?
- 認證用戶和服務器,確保數據發送到正確的客戶機和服務器。
客戶端必須避免中間人攻擊,即除了真正的服務器,任何第三方都無法冒充服務器。
- 加密數據以防止數據中途被竊取。
- 維護數據的完整性,確保數據在傳輸過程中不被改變。
HTTP 和 HTTPS 的區別?
- 端口不同:HTTP 與 HTTPS 使用不同的連接方式,用的端口也不一樣,前者是 80,后者是 443。
個人的想法,實際 HTTPS 也是可以使用 80 端口,但是考慮繼續保持 HTTP 的兼容,只好退而求其次,使用 443 端口。
- 資源消耗:和 HTTP 通信相比,HTTPS 通信會由于加解密處理消耗更多的 CPU 和內存資源。
- 開銷:HTTPS 通信需要證書,而證書一般需要向認證機構申請免費或者付費購買。
HTTPS 可以有效的防止運營商劫持,解決了防劫持的一個大問題。
SSL 加密方式是什么?
對稱密鑰加密,是指加密和解密使用同一個密鑰的方式,這種方式存在的最大問題就是密鑰發送問題,即如何安全地將密鑰發給對方。非對稱加密,指使用一對非對稱密鑰,即公鑰和私鑰,公鑰可以隨意發布,但私鑰只有自己知道。發送密文的一方使用對方的公鑰進行加密處理,對方接收到加密信息后,使用自己的私鑰進行解密。
SSL 協議,即用到了對稱加密也用到了非對稱加密
- 在建立傳輸鏈路時,SSL 首先對對稱加密的密鑰使用公鑰進行非對稱加密。
注意喲,這里 Server 返回給 Client 的不是公鑰( server.pub ),而是 server.crt 。Client 需要使用 ca.key 從 server.crt 中解密出公鑰( server.pub ) 。
- 鏈路建立好之后,SSL 對傳輸內容使用公鑰(
server.pub )對稱加密。
為什么公鑰傳輸的步驟這么復雜呢?
答案請看 《九個問題從入門到熟悉 HTTPS》 文章的如下問題:
- Q5: 那公鑰怎么傳輸
- Q6: 你在逗我么。。。。
- Q7: 怎么知道證書有沒有被篡改?
- Q8: 這樣可以防止第三方冒充服務器么
也就是說,通過 CA 來保證。至于 server.crt 證書是怎么申請的呢?請看 《SSL/TLS 雙向認證(一) – SSL/TLS工作原理》 文章的 「CA 的證書 ca.crt 和 SSL Server 的證書 server.crt 是什么關系呢? 」 問題的解答。
看這塊,我已經要被繞暈了!!!耐心~胖友,理解后會很爽。
什么是單向認證、雙向認證?
- 單向認證,指的是只有一個對象校驗對端的證書合法性。
通常都是 Client 來校驗服務器的合法性。那么 Client 需要一個ca.crt ,服務器需要 server.crt 和 server.key 。
- 雙向認證,指的是相互校驗,Server 需要校驗每個 Client ,Client 也需要校驗服務器。
Server 需要 server.key、server.crt、ca.crt 。Client 需要 client.key、client.crt、ca.crt 。
1)單向認證的過程?
單向認證
-
1、客戶端向服務端發送 SSL 協議版本號、加密算法種類、隨機數等信息。
-
2、服務端給客戶端返回 SSL 協議版本號、加密算法種類、隨機數等信息,同時也返回服務器端的證書,即公鑰證書。
-
3、客戶端使用服務端返回的信息驗證服務器的合法性,包括:
- 證書是否過期。
- 發型服務器證書的 CA 是否可靠。
- 返回的公鑰是否能正確解開返回證書中的數字簽名。
- 服務器證書上的域名是否和服務器的實際域名相匹配
驗證通過后,將繼續進行通信;否則,終止通信。
- 4、客戶端向服務端發送自己所能支持的對稱加密方案,供服務器端進行選擇。
- 5、服務器端在客戶端提供的加密方案中選擇加密程度最高的加密方式。
- 6、服務器將選擇好的加密方案通過明文方式返回給客戶端。
- 7、客戶端接收到服務端返回的加密方式后,使用該加密方式生成產生隨機碼,用作通信過程中對稱加密的密鑰,使用服務端返回的公鑰進行加密,將加密后的隨機碼發送至服務器。
- 8、服務器收到客戶端返回的加密信息后,使用自己的私鑰進行解密,獲取對稱加密密鑰。
在接下來的會話中,服務器和客戶端將會使用該密碼進行對稱加密,保證通信過程中信息的安全。
2)雙向認證的過程?
雙向認證和單向認證原理基本差不多,只是除了客戶端需要認證服務端以外,增加了服務端對客戶端的認證,具體過程如下:
雙向認證
-
1、客戶端向服務端發送 SSL 協議版本號、加密算法種類、隨機數等信息。
-
2、服務端給客戶端返回 SSL 協議版本號、加密算法種類、隨機數等信息,同時也返回服務器端的證書,即公鑰證書。
-
3、客戶端使用服務端返回的信息驗證服務器的合法性,包括:
- 證書是否過期。
- 發型服務器證書的 CA 是否可靠。
- 返回的公鑰是否能正確解開返回證書中的數字簽名。
- 服務器證書上的域名是否和服務器的實際域名相匹配
驗證通過后,將繼續進行通信;否則,終止通信。
- 【新增】4、服務端要求客戶端發送客戶端的證書,客戶端會將自己的證書發送至服務端。
- 【新增】5、驗證客戶端的證書,通過驗證后,會獲得客戶端的公鑰。
- 6、客戶端向服務端發送自己所能支持的對稱加密方案,供服務器端進行選擇。
- 7、服務器端在客戶端提供的加密方案中選擇加密程度最高的加密方式。
- 8、服務器將選擇好的加密方案通過明文方式返回給客戶端。
- 9、客戶端接收到服務端返回的加密方式后,使用該加密方式生成產生隨機碼,用作通信過程中對稱加密的密鑰,使用服務端返回的公鑰進行加密,將加密后的隨機碼發送至服務器。
- 10、服務器收到客戶端返回的加密信息后,使用自己的私鑰進行解密,獲取對稱加密密鑰。
在接下來的會話中,服務器和客戶端將會使用該密碼進行對稱加密,保證通信過程中信息的安全。
如何選擇單向認證還是雙向認證
- 一般一個站點很多用戶訪問就用單向認證。
- 企業接口對接就用雙向認證。
如果想要提高 APP 的安全級別,也可以考慮雙向認證。因為,APP 天然方便放入客戶端證書,從而提高安全級別。
為什么抓包工具還能抓到 HTTPS 數據包并解密成功呢
不是說HTTPS在網絡中傳輸的是密文嗎?這個問題就是中間者攻擊(man in zhe middle)。
中間者攻擊原理圖
- 解決辦法,就是 HTTPS 單向驗證。在客戶端中內置服務器公鑰,在第三步服務器返回的公鑰,除了驗證公鑰的有效性之外,再比對公鑰是不是和內置的公鑰一樣,不一樣說明被中間者攻擊了,就斷開鏈接不在請求了。
- 這個原理的前提是服務器的私鑰沒有泄露,客戶端的代碼不會被破解,道高一尺魔高一丈。信息安全就是在合理的范圍內,選擇比較合適的加密方法,沒有絕對論,只有相對論。在某個范圍內比較安全。
HTTPS 握手會影響性能么?
TCP 有三次握手,再加上 HTTPS 的四次握手,影響肯定有,但是可以接受。
- 首先,HTTPS 肯定會更慢一點,時間主要花費在兩組 SSL 之間的耗時和證書的讀取驗證上,對稱算法的加解密時間幾乎可以忽略不計。
- 而且如果不是首次握手,后續的請求并不需要完整的握手過程。客戶端可以把上次的加密情況直接發送給服務器從而快速恢復,具體細節可以參考 《圖解 SSL/TLS 協議》 。
- 除此以外,SSL 握手的時間并不是只能用來傳遞加密信息,還可以承擔起客戶端和服務器溝通 HTTP2 兼容情況的任務。因此從 HTTPS 切換到 HTTP2.0 不會有任何性能上的開銷,反倒是得益于 HTTP2.0 的多路復用等技術,后續可以節約大量時間。
- 如果把 HTTPS2.0 當做目標,那么 HTTPS 的性能損耗就更小了,遠遠比不上它帶來的安全性提升。
HTTP2
什么是 HTTP2.0 ?
HTTP2.0 ,可以說是SPDY的升級版(其實原本也是基于SPDY設計的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,如下:
- HTTP2.0 支持明文 HTTP 傳輸,而 SPDY 強制使用 HTTPS 。
- HTTP2.0 消息頭的壓縮算法采用 HPACK,而非 SPDY 采用的 DEFLATE 。
HTTP2.0 和 HTTP1.X 相比的新特性?
- 1、新的二進制格式(Binary Format)
HTTP1.x 的解析是基于文本。基于文本協議的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進制則不同,只認 0 和 1 的組合。基于這種考慮 HTTP2.0 的協議解析決定采用二進制格式,實現方便且健壯。
-
同 SPDY 對 HTTP1.1 的改進。
- 2、降低延遲
- 3、多路復用(MultiPlexing)
- 4、header 壓縮
- 5、服務端推送(server push)
Nginx 怎么做 HTTP2.0 的升級改造?
- 1、雖然 HTTP2.0 其實可以支持非 HTTPS 的,但是現在主流的瀏覽器像 Chrome,Firefox 表示還是只支持基于 TLS 部署的 HTTP2.0協議,所以要想升級成 HTTP2.0 還是先升級 HTTPS 為好。
- 2、當你的網站已經升級 HTTPS 之后,那么升級 HTTP2.0 就簡單很多,如果你使用 NGINX ,只要在配置文件中啟動相應的協議就可以了,可以參考 NGINX白皮書NGINX配置HTTP2.0官方指南 。
- 3、使用了 HTTP2.0 那么,原本的 HTTP1.x 怎么辦?這個問題其實不用擔心,HTTP2.0 完全兼容 HTTP1.x 的語義,對于不支持 HTTP2.0 的瀏覽器,NGINX 會自動向下兼容的。
在我們內部的微服務 API 接口,也可以做 HTTP2 的改造,可以參考如下文章:
選讀,作為知識的擴充
- 《Spring Cloud 使用 HTTP2》
- 《再說 SpringBoot2.0 與 HTTP/2》
HTTP2.0 的多路復用和 HTTP1.X 中的長連接復用有什么區別?
- HTTP/1.0:一次請求-響應,建立一個連接,用完關閉;每一個請求都要建立一個連接。
- HTTP/1.1:Pipeling 解決方式為,若干個請求排隊串行化單線程處理,后面的請求等待前面請求的返回才能獲得執行機會。一旦有某請求超時等,后續請求只能被阻塞,毫無辦法,也就是人們常說的線頭阻塞。
- HTTP/2:多個請求可同時在一個連接上并行執行。某個請求任務耗時嚴重,不會影響到其它連接的正常執行。
如下圖所示:HTTP/1.1 對比 HTTP/2
HTTP2.0 多路復用有多好?
最近重新看了 TCP ,發現再看這個問題,真的是有趣!
HTTP 性能優化的關鍵并不在于高帶寬,而是低延遲。TCP 連接會隨著時間進行自我「調諧」,起初會限制連接的最大速度,如果數據成功傳輸,會隨著時間的推移提高傳輸的速度。這種調諧則被稱為 TCP 慢啟動。由于這種原因,讓原本就具有突發性和短時性的 HTTP 連接變的十分低效。
HTTP/2 通過讓所有數據流共用同一個連接,可以更有效地使用 TCP 連接,讓高帶寬也能真正的服務于 HTTP 的性能提升。
服務器推送到底是什么?
服務端推送能把客戶端所需要的資源伴隨著 index.html 一起發送到客戶端,省去了客戶端重復請求的步驟。正因為沒有發起請求,建立連接等操作,所以靜態資源通過服務端推送的方式可以極大地提升速度。具體如下:
- 普通的客戶端請求過程:普通的客戶端請求過程
- 服務端推送的過程:服務端推送的過程
為什么需要頭部(header)壓縮?
假定一個頁面有 100 個資源需要加載(這個數量對于今天的 Web 而言還是挺保守的),而每一次請求都有 1kb 的消息頭(這同樣也并不少見,因為 Cookie 和引用等東西的存在),則至少需要多消耗 100kb 來獲取這些消息頭。HTTP2.0 可以維護一個字典,差量更新 HTTP 頭部,大大降低因頭部傳輸產生的流量。
具體參考:《HTTP/2 頭部壓縮技術介紹》 文章。
- 維護一份相同的靜態字典(Static Table),包含常見的頭部名稱,以及特別常見的頭部名稱與值的組合。
- 維護一份相同的動態字典(Dynamic Table),可以動態地添加內容。
- 支持基于靜態哈夫曼碼表的哈夫曼編碼(Huffman Coding)。
感覺,大學丟掉的網絡知識,又一次回到我的腦子中了。好開心,又可以遺忘一輪啦,哈哈哈哈。
參考與推薦如下文章:
- 《Https 單向認證和雙向認證》
- 《【網絡協議】ping 的工作原理》
- 《HTTP1.0、HTTP1.1 和 HTTP2.0 的區別》
- 《計算機網絡常見面試題》
- 《總結的網絡面試題》
- 《面試/筆試第一彈 —— 計算機網絡面試問題集錦》
- 《通俗大白話來理解 TCP 協議的三次握手和四次揮手》
- 《TCP 數據的傳輸過程》
- 《搞定計算機網絡面試,看這篇就夠了(補充版)》
歡迎關注我們人工智能在新媒體領域應用的公眾號。