基礎面試題 — 計算機網路

Joelixy發表於2019-01-15

有感而發

作為計算機相關專業的必修課之一,計算機網路在程式設計中的地位從未被超越。整個社會都在高度依賴網路所提供的各種服務,我們一邊享受網路所提供的便利,一邊也在通過網路成為被販賣的物件,網路安全的重要性,日益凸顯。此外,如果太依賴於網路,天天生活在網路中,在一定程度上也會削弱我們在實際生活中的各項技能,因此,審時度勢,合理利用網路,方能讓我們活得更出彩。如果我們告別各種電子裝置,迴歸到煤油燈的生活,想想每天都有大把的時間,可以做……也可以做……(反正不會熬夜)。

計算機網路體系結構

計算機網路的體系結構也就是我們熟知的七層網路模型或五層網路模型,接下來從下往上大致介紹下各個層級及其作用:

  • 物理層:其任務是規範物理傳輸媒介相關介面的特性(可理解為把光電訊號轉換成0或1位元資料,根據0或1位元資料轉換成對應的光電訊號);
  • 資料鏈路層:在相鄰節點之間透明傳送被封裝成幀的IP資料包(封裝成幀,透明傳輸);
  • 網路層(IP層):通過選擇合適的路由,為網路系統中的主機提供通訊服務(路由選擇,地址解析等);
  • 傳輸層:通過傳輸層的協議,為不同主機間的應用程式提供通訊服務(通過埠區分程式);
  • 會話層:負責處理不同主機程式間會話的建立、控制和關閉(會話管理,資料流同步);
  • 表示層:負責根據資料格式、編碼、壓縮和解壓縮、加密和解密,轉換計算機和網路通訊間的資料格式;
  • 應用層:為使用者應用程式提供通訊服務,保證通訊雙方的可用性和資料的完整性;

一些關鍵詞

  • ping:ICMP網際控制報文協議,一般使用ICMP協議的回送請求和回送應答測試兩個主機之間的連通性;
  • MTU:Maximum Transfer Unit最大傳送單元,即IP資料包,鏈路層所允許的最大傳輸單元;
  • MSS:Maximum Segment Size最大報文段長度,即傳送到IP層不需要分片的長度;

差錯檢驗

  • 傳輸層:對資料段和頭部整體校驗(IP頭部長度:TCP20位元組,UDP8位元組);
  • 網路層:只校驗首部(IP層首部20位元組);
  • 鏈路層:位元差錯校驗(校驗0和1);

TCP和UDP的區別?

協議 面向連線? 可靠交付? 點對點? 擁塞避免? 流量控制? 面向位元組or報文?
UDP 無連線 盡最大努力但不保證可靠 一對一、多對多、多對一、多對多 不支援 不支援 面向報文
TCP 面向連線 保證可靠 只支援一對一 支援 支援 面向位元組流(會對位元組進行編號)

TCP 為何要三次握手和四次揮手?

TCP是面向連線的,所以在資料傳輸之前要先建立連線,3次握手是為了建立連線,資料傳輸完畢後必須要釋放連線,4次揮手就是為了釋放連線。

  • 三次握手(簡化版)
    1. 服務端建立傳輸控制塊TCB,準備接收客戶端的連線請求並進入LISTEN(收聽)狀態,客戶端建立TCB後向服務端傳送連線請求報文;
    2. 服務端收到後隨即發出確認報文(此時還沒建立連線);
    3. 客戶端收到伺服器端的確認後再發出一次確認報文,服務端收到後建立連線,握手結束。

PS:客戶端最後傳送的那次確認主要是為了防止已失效的連線請求報文突然又傳送到服務端,因而產生錯誤和導致服務端資源浪費。

  • 四次揮手(簡化版)
    1. 客戶端應用程式先向其TCP發出連線釋放報文並停止資料的傳送,進入終止等待狀態
    2. 服務端收到後隨即發出去確認並進入關閉等待狀態,客戶端收到確認後進入終止等待狀態2,若服務端仍有資料需要傳送給客戶端,客戶端仍然需要接收。
    3. 服務端確認沒有需要向客戶端傳送的資料後,服務端應用程式通知TCP釋放連線,並進入最後確認狀態,等待客戶端的確認
    4. 客戶端收到服務端的連線釋放的報文後,向服務端發出確認,服務端收到確認後關閉連線,客戶端在等待最長報文壽命結束後也關閉連線(若服務端超時沒有收到確認,則需要重發釋放連線的請求,此時客戶端會繼續發出確認並重新開啟一個等待計時器;防止已失效的連線請求報文出現在本連線中)

TCP 如何保證可靠的?

TCP協議主要是通過確認和重傳機制來保證可靠交付,TCP會對報文資料進行編號,每個報文段都有起始編號和尾部編號,一個報文段可以理解為一個傳送視窗的大小,也就是傳送方來在未收到對方確認的情況下可以連續傳送的報文大小。

  1. 對於傳送方來說傳送報文段資料時,同時開啟超時計時器,在未收到確認之前都會暫時保留一份副本,傳送方經過一段時間後(由超時計時器控制)就重傳這部分資料(可能是傳送方傳送的報文超時,也可能是接收方傳送的確認超時),並重新設定超時計時器,直到收到確認為止。
  2. 傳送方接收到確認(已收到的報文號段和期待下次接收的報文號段)後,移除保留的對應的報文段副本(從傳送快取中移除),並移動傳送視窗,傳送新的資料。
  3. 接收方把接收到的報文段放到接收快取中,包括按序到達的、但尚未被接收應用程式讀取的資料和未按序到達的資料。接收方等到位元組流中所缺少的位元組收到後,再按序交付給上層的應用程式。
  4. 接收方如果收到的分組被檢測出有差錯或重複的資料就會丟棄,接收方可能會有缺失的報文段,對於接收方來說沒有收到就不會傳送確認,此時傳送方會重傳未被確認的報文段。

TCP 流量控制

流量控制就是讓傳送發的傳送速率不要太快,要讓接收方來得及接收。假設A向B傳送資料,在連線建立時,B告訴A我的接收視窗rwnd="400"(rwnd表示receiver window,位元組單位),假設一個報文段長度是100位元組,A傳送了序號1-100的報文段,還能傳送300位元組,A傳送序號101-200報文段,還能傳送200位元組,此時B傳送了序號1-100報文段和rwnd=300位元組的確認報文,此時A可傳送的大小就是300位元組,如果A已傳送了400位元組,就不允許A再傳送資料了,允許A超時重發舊的資料,但不允許A傳送新資料,總的來說就是接收方控制傳送方傳送資料的速率,以便接收方來得及接收。

TCP 擁塞控制

TCP主要通過慢開始和擁塞避免進行擁塞控制。在不清楚網路負荷的情況下,若把大量資料傳送到網路,那麼就可能引起網路擁塞,所以會先探測一下,即從小到大逐漸增大擁塞視窗(等同於傳送視窗),當網路出現擁塞再把擁塞視窗減小一些,以減少注入到網路中的分組數。

  1. TCP初始化時會把擁塞視窗設定為一個MSS大小,並初始化慢開始門限(調節傳送視窗大小)的值,在每收到一個對新的報文段的確認後,把擁塞視窗增加至多一個MSS的數值(1變2,2變4,4變8),用這樣的方法逐步增大傳送方的擁塞視窗cwnd,使報文注入到網路的速率更加合理。
  2. 隨著傳輸輪次的增加,擁塞視窗的大小曾指數級增長,當擁塞視窗的大小等於慢開始門限的值時,此時會從慢開始切換到擁塞避免,可以理解為把擁塞視窗之前的指數級增長改為線性緩慢增長(經過一個往返時間擁塞視窗僅增加一個MSS大小)。
  3. 隨著擁塞視窗的逐漸增大,當檢測到報文超時(在超時計時器內沒有收到確認),就把慢開始門限的值更新為出現擁塞時擁塞視窗大小的一半,同時把擁塞視窗的大小重新置為一個MSS,並開始執行慢開始演算法,如此往復。

HTTP的組成部分

HTTP由三部分組成:開始行、Header和Body體;

  • 開始行:用於區分是請求行還是響應行
    • 請求行:Method URL HTTP/Version,如:GET /Joelixy/IVAlgorithms HTTP/1.1;
    • 狀態行:HTTP/Version StatusCode StatusMsg,如:HTTP/1.1 404 Not Found;
  • Header
    • Request Header(一般有如圖所示欄位,也可自定義)

      基礎面試題 — 計算機網路

    • Response Header(具體請參考下圖)

      基礎面試題 — 計算機網路

  • Body
    • 一般的POST請求只有相關引數,上傳檔案的POST請求會包含被編碼的檔案資料。

上傳檔案的HTTP請求

  • —$boundary:可以認為是Body的邊界
  • Content-Disposition:用於指定呈現方式,如:from-data:name="txt"
  • Content-Type:
    • application/x-www-form-urlencoded:用來提交文字,不能上傳檔案,用$_POST[]接收
    • multipart/form-data:用來提交表單資料,用$_FILES接收
  • Content-Transfer-encoding:預設的編碼行不通時可指定編碼方式
  • 資料:被上傳的編碼後的資料

GET和POST的區別

  1. GET從服務端獲取資料,POST向服務端傳送資料
  2. GET引數新增到表單的ACTION屬性所指的URL中;POST中將欄位及其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址,使用者看不到這個過程。
  3. 服務端用Request.QueryString獲取變數的值,用Request.Form獲取表單中的資料
  4. GET傳送資料量較小,2KB以內,POST不受限,主要取決於服務端的限制
  5. 安全性不一樣,GET請求直接暴露給使用者了,且還可能被伺服器記錄,有洩漏風險;POST的所有操作對使用者都是不可見的

網路安全

密碼體制

主要有兩種,一種是對稱祕鑰密碼體制,另一種是公鑰密碼體制。

  • 對稱金鑰密碼體制:即加密與解密都是相同的密碼體制,加解密速度快,但是若不對金鑰分發的過程加以保護,金鑰洩漏的風險還是很高。
  • 公鑰密碼體制:使用不同的加密金鑰和解密金鑰,即公鑰和私鑰,公鑰是公開的,私鑰是保密的,公鑰加密的資料只有私鑰能解密,私鑰加密的資料只有公鑰能解密。

金鑰分配

由於密碼演算法是公開的,所以網路的安全性就完全基於金鑰的安全之上,因此金鑰的管理和分發就顯得無比重要了。目前通用的做法是:

  • 用公鑰分發:通過公鑰對臨時會話產生的對稱金鑰進行加密,然後進行分發,私鑰解密後,雙方就按照約定的加密方式進行加解密,對稱金鑰對資料加解密,公私鑰用於對報文鑑別。
  • 雙向驗證:通訊的雙方都有自己的公鑰和私鑰對,通訊時通過證書的解析得到對方的公鑰,然後雙發都有了自己的私鑰和對方的公鑰,這樣就可以互相解密對方的加密資料,只是這種方式效率太低,不適合頻繁的網路請求場景。

數字簽名

籤合同的時候,我們都需要進行簽名,就是為了保證其真實性,通過驗證簽名來表明這份合同的真實性。數字簽名就是為了保證這個資料是某個傳送者傳送的,因為只有它才可以有這樣的簽名,所以數字簽名必須保證三點功能:“報文鑑別、報文的完整性和不可否認”。

  1. 報文鑑別:接收者能夠核實傳送者對報文的簽名,也就是說,接收者可以鑑別該報文的確是傳送者傳送的,其他人無法偽造對報文的簽名。
  2. 報文的完整性:接收者確信所收到的資料和傳送者傳送的完全一樣,沒有被篡改過,這就叫報文的完整性。
  3. 不可否認:傳送者事後不能抵賴對報文的簽名。

HTTPS如何對報文鑑別來保證資料的完整性?

  1. 以客戶端和服務端為例,服務端在傳送報文時,會通過報文摘要演算法對報文進行計算得到報文摘要,然後服務端用自己的私鑰對報文摘要進行簽名,最後把簽名後的報文摘要追加到報文後一起傳送給客戶端。
  2. 客戶端在收到服務端的報文後,把簽過名的報文摘要和報文進行分離後,會做兩件事,(1)客戶端用服務端的公鑰對簽過名的報文摘要解密得到報文摘要,(2)對接收的報文進行報文摘要計算,也會得到一個報文摘要。客戶端對比兩個報文摘要,若相等則說明收到的報文就是服務端傳送的,相等也說明資料沒有被篡改過,否則說明資料被篡改或不是服務端傳送的。
  3. 同理,客戶端傳送報文時也一樣,用自己的公鑰對報文摘要簽名,然後追加到報文後傳送給服務端,服務端用私鑰解密,並做同樣的事情,來對報文進行鑑別。

HTTPS的握手流程

  • 客戶端:向服務端傳送clientHello以及支援的SSL版本號和加密套件、隨機字串(後面協商對稱祕鑰的時候需要)
  • 服務端:向客戶端傳送ServerHello以及支援的SSL版本號和選擇的加密套件、隨機字串和伺服器的證書(被CA機構的私鑰簽名過的證書,有RSA公鑰、域名、版本、簽名使用的加密演算法等,若需要雙向驗證,則需要客戶端也提供相應的證書,此處只考慮單向驗證)
  • 客戶端:支援HTTPS的一般都有個可信的CA表(內建客戶端或系統中),表中有CA的公鑰(CA認證中心的公鑰都是公開的)。客戶端收到服務端的證書時就檢查此證書的發行者是否在自己的可信CA表中。若不在則無法建立加密連線,若在就使用CA表中相應的公鑰對證書校驗並解密得到服務端的公鑰。然後用公鑰加密客戶端產生的隨機字串併傳送給服務端,服務端收到後用私鑰解密得到隨機字串,此時雙方都有三個字串,會用約定的加密方式加密隨機字串生成對稱金鑰。
  • 客戶端:向伺服器傳送一個報文,說明以後客戶端將使用此會話對稱金鑰進行加解密。然後客戶端再向伺服器傳送一個單獨的加密報文,表明客戶端的握手過程已完成。
  • 服務端:也向客戶端傳送一個報文,說明以後服務端將使用此會話金鑰進行加解密,然後服務端再向客戶端傳送一個單獨的加密報文,表明服務端的握手過程已完成。
  • 此時SSL握手已經完成,下面就可以開始SSL的會話;

淘寶頁面傳送HTTP請求的過程

  • DNS解析(查詢過程:本地域名Server(DNS快取記憶體)->根域名Server->COM頂級域名Server
    • 先查詢瀏覽器的DNS快取->系統的DNS快取->DNS伺服器(先查詢自己的DNS快取->根域名Server->COM頂級域名->域名註冊商
    • 如:www.google.com域名,真實的域名是www.google.com.多一個點,瀏覽器向DNS請求時會自動新增該點,表示根域名伺服器。
    • DNS快取:瀏覽器快取-系統快取-路由器快取-IPS伺服器快取-跟域名Server-頂級域名Server-主域名Server
  • TCP建立連線
    • 拿到域名IP地址後,客戶端以一個隨機埠向伺服器的Web程式80埠發起連線請求,連線請求經過下面4層網路模型層層封裝到達服務端,進入到服務端的核心的TCP/IP協議棧,識別連線請求層層解開資料包,找到80埠到達Web程式,
  • 傳送HTTP請求(三部分)
    • GET:要求伺服器將URL定位的資源放在響應報文的資料部分傳送給客戶端,URL和引數通過“?”分割
    • POST:將資料封裝在HTTP請求資料中(HTML HEAD)
  • 伺服器處理HTTP請求並返回HTTP報文
    • 處理後就把資料返回給客戶端HTML資料
  • 客戶端解析資料並渲染頁面
    • 客戶端解析HTML拿到資料,然後開始渲染頁面
  • 斷開TCP連線
    • 服務端在一段時間後若沒有收到客戶端的請求,連線就會關閉;

總結

網路是那麼的重要,幾乎每個專案都避不開它,而且還可能會出現很多奇奇怪怪的網路問題,所以有關網路的相關基礎理論是編寫和除錯網路模組的必備知識,最好通過除錯來了解請求是如何建立和相互通訊的。


PS:以上描述的相關知識點,由個人總結並進行了簡化,難免會有不足和錯誤的地方,歡迎大家指正!

相關文章