1. 程式人生 > >打牢基礎 | 網路基礎知識十二問

打牢基礎 | 網路基礎知識十二問

## 前言 過年倒計時~ 今天是網路篇的最後一篇,網路知識也是面試常考內容,所以必須要把基礎知識打牢。 網路十二問,送給大家。 ## 這些問題,你能答上來嗎 我總結了下網路方面會涉及到的一些問題,大家看看,如果都能答上來,那這篇文章就可以略過了。 * 網路通訊的過程,以及中間用了什麼協議? * TCP連線過程,三次握手和四次揮手,為什麼? * 常用的狀態碼。 * 講一下TCP協議和UDP協議的區別和場景 * socket和WebSocket * Https的連結建立過程 * 講解一下數字簽名,為什麼真實可靠 * 證書鏈安全機制 * 建立過程耗時,那麼怎麼優化呢? * 講一下Http和Https的區別 * Http傳輸圖片有哪些方式 * 怎麼實現分塊傳輸,斷點續傳? ## 網路通訊的過程,以及中間用了什麼協議 這個問題我之前專門做了一個動畫,大家可以翻到上一篇文章看看: [網路資料原來是這麼傳輸的(結合動畫解析)](https://mp.weixin.qq.com/s/PFhA3WdS-2aSdbWqGyTETQ) 再簡單總結下: 客戶端: * 1、在瀏覽器輸入網址 * 2、瀏覽器解析網址,並生成`http`請求訊息 * 3、瀏覽器呼叫系統解析器,傳送訊息到DNS伺服器查詢域名對應的`ip` * 4、拿到ip後,和請求訊息一起交給作業系統協議棧的`TCP模組` * 5、將資料分成一個個資料包,並加上TCP報頭形成`TCP資料包` * 6、TCP報頭包括髮送方埠號、接收方埠號、資料包的`序號、ACK號`。 * 7、然後將`TCP訊息`交給IP模組。 * 8、IP模組會新增`IP頭部`和`MAC頭部`。 * 9、IP頭部包括`IP地址`,為IP模組使用,MAC頭部包括MAC地址,為資料鏈路層使用。 * 10、`IP模組`會把整個訊息包交給網路硬體,也就是資料鏈路層,比如乙太網,WIFI等 * 11、然後網絡卡會將這些包轉換成`電訊號或者在光訊號`,通過網線或者光纖傳送出去,再由路由器等轉發裝置送達接收方。 伺服器端: * 1、資料包到達伺服器的`資料鏈路層`,比如乙太網,然後會將其轉換為資料包(數字訊號)交給`IP模組`。 * 2、`IP模組`會將MAC頭部和IP頭部後面的內容,也就是TCP資料包傳送給TCP模組。 * 3、`TCP模組`會解析TCP頭資訊,然後和客戶端溝通表示收到這個資料包了。 * 4、`TCP模組`在收到訊息的所有資料包之後,就會封裝好訊息,生成相應報文發給應用層,也就是HTTP層。 * 5、`HTTP層`收到訊息,比如是HTML資料,就會解析這個HTML資料,最終繪製到瀏覽器頁面上。 ## TCP連線過程,三次握手和四次揮手,為什麼? ### 連線階段(三次握手): * 建立套接字`Socket`,伺服器會在啟動的時候就建立好,客戶端是在需要訪問伺服器的時候建立套接字 * 然後發起連線操作,其實就是Socket的`connect`方法 * 這時候客戶端會生成一個TCP資料包。這個資料包的TCP頭部有三個重要資訊:`SYN、SEQ、ACK`。 >SYN,同步序列編號,是TCP/IP建立連線時使用的握手訊號,如果這個值為1就代表是連線訊息。 >SEQ,資料包序號,是傳送資料的一個順序編號。 >ACK,確認號,是接收資料的一個順序編號。 * 所以客戶端就生成了這樣一個數據包,其中頭部資訊的`SYN`設定為1,代表連線。`SEQ`設定一個隨機數,代表初始序號,比如100。`ACK`沒有設定,因為是第一次傳送資料,不需要`ACK`。 * 然後伺服器端收到這個訊息,知道了客戶端是要來連線的`(SYN=1)`,知道了傳輸資料的初始序號`(SEQ=100)`。 * 伺服器端也要生成一個數據包傳送給客戶端,這個資料包的TCP頭部會包含`三個值`:表示我也要連線你的`SYN(SYN=1)`,我已經收到了你的上個數據包的確認號`ACK(ACK=SEQ+1=101)`,以及伺服器端隨機生成的一個序號`SEQ(比如SEQ=200)`。 * 最後客戶端收到這個訊息後,表示客戶端到伺服器的連線是無誤了,然後再發送一個數據包表示也確認收到了伺服器發來的資料包,這個資料包的頭部就主要就是一個`ACK值(ACK=SEQ+1=201)`。 * 至此,連線成功,三次握手結束,後面資料就會正常傳輸,並且每次都要帶上TCP頭部中的`SEQ和ACK值`。 這裡有個問題是關於為什麼需要`三次握手`? 最主要的原因就是需要通訊雙方都確認自己的訊息被準確傳達過去了。 A傳送訊息給B,B回一條訊息表示我收到了,這個過程就保證了A的通訊能力。 B傳送訊息給A,A回一條訊息表示我收到了,這個過程就保證了B的通訊能力。 也就是四條訊息能保證雙方的訊息傳送都是正常的,其中B回訊息和B發訊息,可以融合為一次訊息,所以就有了`三次握手`。 ![](https://img2020.cnblogs.com/blog/2177591/202102/2177591-20210202110206994-508588705.png) ### 資料傳輸階段: 資料傳輸階段有個改變就是`ACK確認號`不再是`SEQ+1`了,而是`SEQ+資料長度`。例如: * A傳送給B的資料包(SEQ=100,長度=1000位元組) * B回給A的資料包(ACK=100+1000=1100) 這就是一次資料傳輸的頭部資訊,`ACK`代表下個數據包應該從哪個位元組開始所以等於上個數據包的SEQ+長度,SEQ就等於上個數據包的ACK。 當然,TCP通訊是雙向的,所以實際資料每個訊息都會有`SEQ和ACK`: * A傳送給B的資料包(ACK=200,SEQ=100,長度=1000位元組) * B回給A的資料包(ACK=100+1000=1100,SEQ=上一個資料包的ACK=200,長度=500位元組) * A傳送給B資料包(SEQ=1100,ACK=200+500=700) ![](https://img2020.cnblogs.com/blog/2177591/202102/2177591-20210202110214712-1601000342.png) ### 斷開階段(四次揮手): 和連線階段一樣,TCP頭部也有一個專門用作關閉連線的值叫做FIN。 * 客戶端準備關閉連線,會發送一個`TCP資料包`,頭部資訊中包括`(FIN=1代表要斷開連線)`。 * 伺服器端收到訊息,回覆一個數據包給客戶端,頭部資訊中包括`ACK確認號`。但是此時伺服器端的正常業務可能沒有完成,還要處理下資料,收個尾。 * 客戶端收到訊息。 * 伺服器繼續處理資料。 * 伺服器處理資料完畢,準備關閉連線,會發送一個`TCP資料包`給客戶端,頭部資訊中包括(FIN=1代表要斷開連線) * 客戶端端收到訊息,回覆一個數據包給伺服器端,頭部資訊中包括`ACK確認號`。 * 伺服器收到訊息,到此伺服器端完成連線關閉工作。 * 客戶端經過一段時間(2MSL),自動進入`關閉狀態`,到此客戶端完成連線關閉工作。 >MSL 是 Maximum Segment Lifetime,報文最大生存時間,它是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。 這裡有個問題是關於為什麼需要四次揮手? A傳送斷開訊息給B,B回一條訊息表示我收到了,這個過程就保證了A斷開成功。 B傳送斷開訊息給A,A回一條訊息表示我收到了,這個過程就保證了B斷開成功。 其實和連線階段的區別就在於,這裡的B的確認訊息和斷開訊息`不能融合`。因為A要斷開的時候,B可能還有資料要處理要傳送,所以要等正常業務處理完,在傳送斷開訊息。 ![](https://img2020.cnblogs.com/blog/2177591/202102/2177591-20210202110223745-1631386220.png) ## 常用的狀態碼 * `1XX` - 臨時訊息。伺服器收到請求,需要請求者繼續操作。 * `2XX` - 請求成功。請求成功收到,理解並處理。 * `3XX` - 重定向。需要進一步的操作以完成請求。 * `4XX` - 客戶端錯誤。請求包含語法錯誤或無法完成請求。 * `5XX` - 伺服器錯誤。伺服器在處理請求的過程中發生了錯誤。 常見狀態碼: `200 OK` - 客戶端請求成功 `301` - 資源(網頁等)被永久轉移到其它URL `302` - 臨時跳轉 `400 Bad Request` - 客戶端請求有語法錯誤,不能被伺服器所理解 `404 - 請求資源不存在`,錯誤的URL。 `500` - 伺服器內部發生了不可預期的錯誤。 `503 Server Unavailable` - 伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常。 ## 講一下TCP協議和UDP協議的區別和場景 我先說兩個場景,大家可能就比較能理解了。 1) 第一個場景,`瀏覽網頁`。(TCP場景) * 我們訪問網頁,網頁肯定要把所有資料都正確的顯示出來吧,如果這個過程中丟包了,那麼肯定也會重新傳包,不可能只顯示一部分網頁(保證資料正確性) * 同樣,網頁中的內容肯定也需要是`順序`的。比如我一個抽獎,不可能還沒抽就把獎給你了。(保證資料的順序) * 再來,在這個對資料要求嚴格的過程中,我們肯定需要兩方建立起一個`可靠`的連線,也就是我們上述說到的要經過三次握手才開始傳輸資料,並且每次發資料包都需要回執(面向連線的) * 而這種連線中傳輸資料就是用的`位元組流`,也就是有根管道,你想怎麼傳資料都行,想怎麼接受資料也都可以,只要在這一根管道里面。 所以這種需要`資料準確、順序不能錯、要求穩定可靠`的場景就需要用到TCP。 2)第二個場景,打遊戲。(UDP場景) 打遊戲最最重要的就是即時,不然我這個技能發出去了你那邊還沒被打中,這就玩不了了。 * 所以`UDP`是需要保證資料的`即時性`,而不保證每個資料包都正確接收到,即使丟包了,也不會去找丟的那個是什麼包,因為要顯示當前時間的當前資料包。(不保證資料正確性和資料順序,可能會丟包) * 同樣,為了資料的即時性,`UDP`也就不會去建立連線了,不需要什麼三次握手,每次你還要確認收沒收到。管你收沒收到,我只要快速把每個資料包丟給你就行了。(面向無連線的) * 因為是`無連線`的,所以就不需要用到位元組流,直接每次丟一個`資料報`給你,接收方也只能接受一個數據報(不能和其他傳送方的資料報混淆)。(基於資料報的) 如果你還是有點暈,可以看看這篇文章(亞當和夏娃),很形象的比喻: https://www.zhihu.com/question/51388497?sort=created ## socket和WebSocket 雖然這兩個貨名字類似,但其實不是一個層級的概念。 * `socket`,套接字。上文說過了,在TCP建立連線的過程中,是呼叫了Socket的相關API,建立了這個連線通道。所以它只是一個介面,一個類。 * `WebSocket`,是和HTTP同等級,屬於應用層協議。它是為了解決長時間通訊的問題,由HTML5規範引出,是一種建立在TCP協議基礎上的全雙工通訊的協議,同樣下層也需要TCP建立連線,所以也需要socket。 >科普:WebSocket在TCP連線建立後,還要通過Http進行一次握手,也就是通過Http傳送一條GET請求訊息給伺服器,告訴伺服器我要建立WebSocket連線了,你準備好哦,具體做法就是在頭部資訊中新增相關引數。然後伺服器響應我知道了,並且將連線協議改成WebSocket,開始建立長連線。 如果硬要說這兩者有關係,那就是`WebSocket`協議也用到了`TCP連線`,而TCP連線用到了`Socket`的API。 ## Https的連線建立過程 說完了HTTP和TCP/IP,再說說`HTTPS`。 上一篇文章說了HTTPS是怎麼保證資料安全傳輸,[連結