計算機網路層次與對應協議的理解

李志成發表於2018-06-02
  • 應用層
    • 對資料的具體應用 HTTP/DNS/FTP/NFS/SMTP/POP3/IMAP/SNMP等
  • 表示層
    • 對資料進行格式轉換,加解密,解壓縮等(沒有協議)
  • 會話層
    • 會話管理,控制應用之間的通訊,比如訪問驗證 (沒有協議)
  • 傳輸層
    • 通訊雙方資料傳輸。TCP面向連線可靠/順序/流量控制/全雙工/多路複用;UDP非面向連線不可靠,但傳輸經濟
  • 網路層
    • 路由選擇合適的鏈路。IP/OSPF。IP屬於外部網路,OSPF是內部網路(AS-自治系統)
  • 資料鏈路層
    • 定義資料幀在鏈路上的傳輸無差錯。封裝成幀->透明傳輸->差錯檢測
  • 物理層
    • 規定傳輸媒體(介質)的介面相關的特性。規定機械規格和在媒體上的具體傳輸方式(電流/光等),使用各種辦法傳輸bit
      • 機械特性 形狀、尺寸、引腳數等規格
      • 電氣特性 電纜等線路上的電壓範圍等
      • 功能特性 某一電壓表示的含義
      • 過程特性 指定各種可能事件出現順序

1. 物理層

物理層主要跟電氣相關。比如,通訊訊號有模擬訊號,數字訊號;使用電纜或者光纖等就不做多介紹了

2. 資料鏈路

資料鏈路在通道中通訊有兩種:點對點(PPP)和廣播通道。

2.1 點對點的通道的資料鏈路層

點對點的資料鏈路層有3個基本問題:封裝成幀、透明傳輸和差錯檢測

2.1.1 封裝成幀

資料鏈路層把網路層的IP資料頭尾包封裝為幀,並且傳遞給物理層傳輸bit。幀的長度是有最大限制的,不能超過。同時幀中的資料部分儘可能大於首部和尾部,提高傳輸效率。

2.1.2 透明傳輸

由於幀的首部(00000001)和尾部(00000100)使用1位元組來做定界符(非可列印字元),如果資料部分出現了怎麼辦?比如二進位制資料。

為了保證任何資料都能傳輸,因此要做到透明傳輸。這個透明是指 A網路層 --> B網路層,這個傳輸過程中接受的是原樣資料。A網路層發什麼,B的資料鏈路層就給B的網路層傳遞什麼。

那麼,如果是含有幀定界符的資料內容呢?那就要做轉義,前面新增1位元組(16進位制1B)。

2.1.3 錯誤檢測

這個是資料鏈路層最重要的部分。因為每一個層次都進行一次資料封裝;也會透明傳輸,因為通訊雙方同層次之間的通訊並不需要知道互相的下一層次做了些什麼處理,也就說同層次通訊是透明傳輸的。錯誤檢測是資料鏈路層相對其他層次不一樣的。

錯誤檢測,差錯是指位元差錯。目前採用的是迴圈冗餘檢驗CRC。資料需要分組,每組K個位元,CRC運算就是在這K個位元後面新增n位冗餘碼,然後構成一個幀(k+n)傳送。

模2運算是CRC的核心部分。冗餘碼的得到方法是;M 2^n ==> M << n ==> M的二進位制加上n個0,然後把(k+n)位模2除以P(n+1位)為,其中商是Q,餘數是R(n位)。那麼這個R就是幀檢驗碼FCS。最後就是(2^n M + FCS)

需要有模2運算的基礎,該運算是有加減乘除的。其實跟二進位制的四則運算一樣,不同的是不管進位,錯位,只管當前對應位的運算。我們知道乘法和除法都是基於加減法的,因為通過豎式可以知道,最終乘法是相加,除法是相減。差異就在這加減法上,沒有進位。

模2加法:

1001

1101

——

0100

模2減法:

1100

1101

——

0001

可以看出,模2加減法是一樣的,也是跟異或運算一樣的

接收端如何檢驗?把接收的(k+n)對P模2除法得出的餘數R。如果是0,那就說明無差錯。

P這個數的選取很講究的,通過P(x)得到。比如,用:

P(X) = = X^2 + X^1 + 1

表示1101。其中還有CRC16,CRC32等

注意:資料鏈路只是保證資料無差錯,不能保證資料是否重複,是否順序,是否丟失。

2.2 使用廣播的資料鏈路層

廣播是乙太網(一種區域網)上的傳播方式。簡單理解就是通過一條匯流排連線在一起的網路,一臺機器傳送資料,其他機器都能接收到。機器針對不是發給自己的機器機型丟棄(所以說區域網不安全,可以不丟棄的呀)。乙太網使用曼切斯特編碼。乙太網最大問題就是競爭匯流排,在傳輸之前都檢測是否被佔用,如果被佔用需要等待一定時間再次傳輸。

3. 網路層

主要的協議有IP協議/ICMP協議/ARP/RARP。該層的傳輸通過封裝成IP資料包。ICMP報文也是使用IP資料包的,但是一般認為同屬於網路層。

3.1 常用的3種IP地址

A類:

  • 網路號1位元組,首位0固定,剩餘7位。2^7 - 2可用,因為網路號全零表示本網路。恰好全1則是127是本地迴環地址。
  • 主機號3位元組。2^24 - 2可用。全零可以指定所在網路。5.6.7.8中5.0.0.0指定所在網路;全1 => 5.255.255.255表示所在網路所有主機
  • IP地址空間佔50%
    B類:
  • 網路號2位元組,10固定。地址空間佔25%
    C類:
  • 網路號3位元組,110固定。地址空間佔12.5%

3.2 IP地址與硬體地址(MAC地址)

image

在Ip層只能看到IP資料包,資料包中的源地址與目標地址始終是Ip1與Ip2,中間經過的兩個路由只是轉發。路由器根據地址IP找到下一個同網路的路由。對於同網路如何傳輸過去?
在資料鏈路層中的Mac幀中源地址和目的地址一直改變。這個是區域網的資料傳輸方式

出現兩個問題:

  1. 路由怎麼知道下一個路由的Mac地址,也就是IP與實體地址對映表如何得出
  2. 路由表怎麼得出。路由器互相交換資訊得到。

3.2.1 地址解析ARP與逆地址解析RARP

ARP:知道IP如何找到實體地址
RARP:知道實體地址怎麼知道IP

ARP:
網路層使用IP,但是實際在鏈路傳輸資料幀還是必須使用網路實體地址。每一個主機都有一個ARP高階快取(有過期時間),存放本地的機器IP與實體地址對映表。我們知道快取就是有就用,無就重新獲取。使用了一個廣播的方式,比如你在群上問:

你(A):我的IP是209.0.0.5,硬體地址是00-00-C0-15-AD-18,209.0.0.6(B)主機硬體地址發我一下?
群上所有人都接收到了

B看到資訊的IP是自己,就回復:我的地址是209.0.0.6,硬體地址是啥啥..(注意這裡是單播,指定源地址與目的地址)

  • 問:為什麼使用IP,然後再去ARP獲得硬體地址去傳輸;而不是直接使用實體地址?
  • 答:各式各樣的網路,硬體地址很不同,不能要求全網所有都要同一種網路。因此網路層統一的IP地址可以解決這個問題。虛擬網路互聯。

ARAP:這個知道實體地址,就好像你知道是誰,那就直接問他IP是什麼好啦。

注意:IP資料包格式就不介紹了,比較複雜,可以看謝希仁的《計算機網路》

3.3 子網

問題是IP地址只是分3級,需要分更多怎麼辦

IP地址 = <網路號><子網號><主機號>

如何判斷是同一個網路,而且還是同一個子網?

  • A類:255.0.0.0
  • B類:255.255.0.0
  • C類:255.255.255.0

原理是通過與運算(AND)

劃分子網之後,那麼就變成子網之間傳輸也是需要至少一個路由器的。首先通過子網掩碼判斷是否該網路,如果不是則交給路由傳遞該相應的子網。

3.4 超網-無分類編址CIDR

3級變成2級:

IP = <網路字首><主機號>

可以使用斜線/寫法,"/"後說明網路字首的長度:

128.14.35.7/20 說明網路字首是前20位

還可以使用星號*:

0001101100*,星號全面的是字首,後面是主機號可以是任意數。這種IP地址有一個問題,就是有可能會匹配多個網路:

  • 大學:11010*
  • 學院:11010001*
  • 某系:110100010001*

這個時候,如果IP地址是110100010001111...怎麼辦?書哪一個網路?最長字首匹配原則!!!

還有的問題是,怎麼在路由表中更具網路字首查詢網路呢?二分查詢,因為bit要麼0,要麼1,可以使用二叉樹結構儲存路由表。

image

3.5 ICMP網際控制報文協議

主機或者路由器報告差錯情況等。差錯報文與詢問報文

  • 差錯報文 (被動接收的)
    • 終點不可達 路由器或者主機(以下統稱主機)不能交付資料包(交付給某主機或者主機的某個埠)會傳送
    • 源點抑制 主機網路阻塞就向源點傳送,告知源點減慢速度
    • 時間超過 TTL等於0的時候
    • 引數錯誤 資料包首部引數不正確就傳送
    • 改變路由(重定向)主機接受到資料包,但是認為有更好的路由選擇,則會向源點傳送該報文
  • 詢問報文 (主動請求的)
    • 回送請求和回答:就是簡單的回答,測試可達性.應用層的ping程式就是使用該方法
    • 時間戳請求和回答:進行時間同步和測量時間

3.6 ICMP的簡單應用

ping是應用層直接應用網路層的例子,用於測試連通性。還有的就是traceroute(win是tracert),跟蹤一個分組從源點到終點的路徑

traceroute原理:源機器向目標機器傳送IP資料包,資料包是無法交付的UDP使用者資料包。第一次請求設定TTL=1,到達路由R1,TTL減1為0,這時候R1把資料包丟棄,並且向源主機傳送ICMP時間超時報文。這樣一直下去,找到目的主機,因為不可交付的UDP使用者資料包,因此最後目的主機向源主機傳送不可達的ICMP錯誤報告報文。

3.7 路由選擇協議

  1. IGP,內部閘道器協議:AS內部的路由選擇協議,比如,RIP,OSPF。
  2. EGP,外部閘道器協議:AS之間的路由選擇協議,比如,BGP。

3.7.1 RIP內部閘道器協議

基於距離向量的路由選擇協議。直接連線的網路距離定義為1,之後沒經過一個路由器到達的網路,則距離加1;RIP中距離稱為"跳數"。並且規定最多經過15個路由,因此距離為16認為不可達。15?可見RIP適合小型的網際網路。

特點:

  1. 僅和相鄰路由(同網路)交換資訊
  2. 交換自身路由表資訊(互相傳送RIP報文)
  3. 固定時間交換,比如30秒

注意:新加入的路由器只是知道直接相連的距離為1,經過與其他路由交換資訊就會知道本AS的路由表資訊了。

3.7.2 OSPF內部閘道器協議

可以理解其實跟RIP的原理有點相似,但是OSPF使用分散式的鏈路狀態協議,而不僅僅是單純的距離,還考慮了鏈路的阻塞,時延,距離,頻寬,費用等鏈路狀態。

3.7.3 BGP外部閘道器協議

BGP - 邊界閘道器協議。為什麼不同AS不使用上面兩種協議?主要一下兩個原因:

  1. 因特網規模太大,使得AS之間路由選擇非常困難
    • 在因特網主幹網上使用OSPF效能低,並且AS對度量的尺度不一等。
  2. AS之間路由選擇必須考慮有關的策略。比如AS1需要經過AS3才能到AS2,此時AS3不想讓AS1經過,或者需要服務費。因此AS之間路由選擇需要更多選擇策略。這些策略是選擇較好的而不是最佳的。

原理:
每個AS至少需要一個BGP發言人-BGP邊界路由器,互相通過TCP連線交換路由資訊。交換的資訊就是要到達某個網路需要經過一系列的AS。比如AS2,說要經過N1,需要經過AS2。AS1接受後,說經過N1,需要經過(AS1,AS2)。

4 傳輸層

面向連線的TCP與無連線的UDP。網路層解決了資料如何從源主機到達目標主機,那麼傳輸層則在網路層的基礎上控制具體的傳輸策略。比如TCP可靠服務(對丟失/重複/失序進行處理)、流量控制、阻塞控制

4.1 TCP 傳輸控制協議

瞭解TCP的報文頭,並且根據報文頭來學習TCP協議是非常好的方法,能夠更好的理解TCP報文頭和TCP的功能。其實不管是哪一個協議也是如此的。

  • 面向連線。3次握手建立連線,4次握手斷開連線。
  • 無差錯、不丟失、不重複、並且按序到達(超時重傳,接收和傳送視窗,阻塞控制)
  • 只能有兩個端點,一對一
  • 全雙工通訊
  • 面向位元組流。應用層交下來的的資料被看成位元組流。應用交付下一層的資料大小是無限制的,就像是一個流水線一樣。只要寫入的資料裝滿緩衝區或者關閉寫操作就傳送一個報文段。

其實最重要的是TCP如何實現可靠傳輸?

  • 出現差錯就丟棄
  • 每一個分組,接收方都需要回復ACK確認。否則傳送方會一直髮(當然等待一段往返時間RTT)。
  • 重複則丟棄,並且回覆ACK,告述傳送方不要再再發了
  • 按序到達。傳送方會有傳送視窗,會按順序移動視窗進行傳送。

如何實現流量控制?

  • 接收方有接收視窗,如果來不及接收和處理資料會告訴傳送方縮小傳送視窗,減緩速率,實現流量控制

連線的3次握手:

image

  • 問:ACK=1是確認報文的意思,那麼對哪一個報文進行確認?
  • 答:注意到seqack了嗎。seq=x表示該報文的序列號x可以識別該報文。服務端回覆中的ack=x+1,則表示目前x以及以前的都接受成功,可以傳送x+1了!這就起到了針對某一個報文就行傳送ACK確認。

釋放連線的4次握手:

image

  • 問:為什麼連線需要3次,但是釋放需要4次?
  • 答:因為在建立連線的時候服務端把ACKSYN一起傳送了,因為建立連線服務端已經準備好了。而在釋放連線的時候;客戶端申請釋放的時候,服務端接收到申請,但是還沒有準備好,比如最後一個分組的ACK還沒有接收到,這個時候就先對客戶端回覆ACK;等到準備就緒才回復FIN。就這樣多了一次握手。

半關閉狀態:

TCP是半雙工的。因此允許雙方獨立的關閉。如果一方結束髮送資料給對方,那麼可以告訴對方完成資料傳送,但是仍然可以接收對方發來的資料,直到對方也結束資料傳送以關閉連線。下圖中系統呼叫read返回0的時候,就是對方要關閉連線的時候。

半關閉

TCP狀態轉移 netstat命令

TCP從建立到關閉,通訊雙方的狀態,具體如下圖。值得注意的是,關閉連線可以分為主動關閉和被動關閉,這兩個的狀態轉移是不一樣的。被動的很好理解,主動的就稍微複雜些。比如FIN_WAIT_1(主動傳送FIN之後)/FIN_WAIT_2(只是收到ACK)/CLOSING(傳送了FIN還沒收ACK後收到對方發的FIN,那就一起關閉吧)/TIME_WAIT(等待關閉,等待2個報文最大生存時間,看看對方是否接收到該給它的ACK,畢竟不能不辭而別)

TCP狀態轉移

TCP狀態轉移

主動關閉中必然會存在的狀態有兩個:FIN_WAIT/TIME_WAIT。並且從FIN_WAITTIME_WAIT必須接收到一個ACK和一個FIN,可以同時接收,也可以任意先後。因此會有3種可能:

  • ACKFIN同時接收並且對此發確認ACK-->TIME_WAIT
  • ACK先收到-->FIN_WAIT_2(等待FIN後發ACK)-->TIME_WAIT
  • FIN先到(這個時候幾乎是雙方同時要求關閉,對對方的FIN進行確認ACK)-->CLOSING(等待對方對我方FINACK)-->TIME_WAIT

TIME_WAIT的作用

  • 可靠地終止TCP連線
  • 保證遲來的TCP報文有足夠時間被識別並且丟棄
    • 一個TCP埠不能唄同事開啟,TCP連線處於TIME_WAIT狀態的時候,我們無法佔用該埠並且重新開啟連線。假設TIME_WAIT不存在,那麼我們可以重新建立一個新的TCP連線(IP與埠一致),那麼新的連線可能會接收到原來連線的報文段,這明顯是不正確的。
    • 為什麼是2MSL報文最大生存時間?因為經過這段時間的遲到的報文會直接被路由器丟棄,可以安全的建立連線
    • 那能不能馬上建立連線?客戶端建立連線使用的是隨機埠(能保證不是一樣的埠),因此可以馬上見建立。對於服務端,可以通過socket選項SO_REUSEADDR來強制啟動(當然後果你是需要知道的啦)

復位報文

啥是復位報文?TCP報文的報文頭中有標記位,其中RST告訴對方要關閉或者重新連線。在某些特殊情況寫會傳送此報文。

1.訪問不存在的埠

其實如果埠還在背佔用的時候,比如在TIME_WAIT狀態的時候也是會發復位報文。

# 在一個終端中使用tcpdump抓包
# Flags [S] 說明是一個SYN同步報文,要求建立TCP連線
# Flags [R.] 說明是一個有RST復位報文,要求關閉連線,並且確認收到SYN報文。注意到win 0,這個說明不要回應這個復位報文
> sudo tcpdump -nt -i lo0 port 54321
IP 127.0.0.1.49953 > 127.0.0.1.54321: Flags [S], seq 1166333184, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 930108577 ecr 0,sackOK,eol], length 0
IP 127.0.0.1.54321 > 127.0.0.1.49953: Flags [R.], seq 0, ack 1166333185, win 0, length 0

# 另一個輸入
> telnet 127.0.0.1 54321
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
2.異常終止連線

TCP提供了異常終止連線的方法。通過socket選項SO_LINGER來主動傳送復位報文

3.處理半開啟連線

就是通訊一方仍然持有連線,但是另一方已經斷開了。比如伺服器要重啟,傳送關閉連線報文,但是客戶端由於網路原因(比如斷網)接收不到報文,當伺服器重啟完畢和客戶端重新連線上網路的時候,服務端已經是沒有這個連線,但是客戶端還是保持這個連線的。如果客戶端給服務端傳送資料,那麼服務端就會給客戶端傳送復位報文

TCP互動資料流

TCP報文段按照大小可以分為兩種:互動資料和成塊資料。互動資料是比較小的,包含較少位元組,比如telnet和ssh。成塊資料大小經常是TCP報文段最大長度。

比如,客戶端使用telnet訪問服務端。在傳遞過程中的就是互動資料流。客戶端傳送的ACK是不包含資料的(馬上對接收的報文段確認);相反服務端的ACK報文段一般都會帶有資料的,一方面可以確認客戶端發來的報文段,另一方面可以就其請求做出響應返回資料。服務端這種處理是延遲確認;就是先不急著傳送確認,而是等服務端是否有資料要傳送,如果有帶上一起發就好。這樣的優點就是減少傳輸微小的報文段傳輸。那麼客戶端怎麼不這麼做?等了,但是等不到啊,因為telnet來訪問的話,需要使用者敲鍵盤啊,太慢了。

TCP成塊資料流

成塊資料流,很好的例子就是使用ftp下載大檔案。

請求過程很可能是:

  • 客戶端請求下載檔案
  • 服務端傳送大報文段1
  • 服務端傳送大報文段2
  • 服務端傳送大報文段3
  • 服務端傳送大報文段4
  • 客戶端ACK確認接收報文段1到4

這種情況,傳送方連續傳送多個報文段,接收方可以一次性進行確認。

帶外資料

帶外(Out Of Band, OOB)資料。用於迅速告訴對方,本端發生的重要事件。因此會比普通資料(帶內資料)的優先順序要高,不放緩衝區,不排隊,立即傳送,立即讀取。TCP中可以使用緊急指標標誌來實現。

4.2 UDP 使用者資料包協議

  • 無連線
  • 盡大可能交付
  • 面向報文。應用層往下發的報文,直接加上首部就交給網路層,UDP一次性交付一個完整報文給網路層。應用給多大,我傳送多大。具體分片由IP協議處理
  • 支援一對一,一對多,多對多
  • 沒有阻塞控制。就是網路的阻塞不會導致主機傳送速率降低。

5 應用層

HTTP/DNS/FTP等。待補充

5.1 HTTP 超文字傳輸協議

求是就是通過TCP連線,兩臺主機按照HTTP協議規定的文字格式進行互相通訊。比如第一行是什麼,第二行是什麼等等。完全可以使用變成語言通過TCP連線來實現一個簡單的HTTP請求。

5.2 DNS域名系統

使用UDP協議。就是根據域名查詢對應的IP。比如通過瀏覽器請求某個網站:

  • 首先是瀏覽器的DNS快取
  • 系統的DNS快取
  • 系統的hosts
  • 請求DNS伺服器

6 Linux或者Mac上的小應用

為了加深理解,這裡推薦一些命令

6.1 檢視ARP快取記憶體

用於檢視和設定本地的ARP快取記憶體的。比如想看ARP請求過程,這個時候就需要先刪除快取,重新請求一次啦。

# 刪除
arp -d 192.168.0.1

# 設定
arp -s IP地址 MAC地址

# 檢視
arp -a

6.2 tcpdump 檢視ARP通訊過程

tcpdump 是一個抓包命令。有了抓包,那怎麼觸發ARP請求呢?只要使用IP協議都能觸達ARP。可以使用telnet簡歷TCP前就需要進行ARP請求;或者使用ping命令(不過要注意的是,ARP之後就會發ICMP報文)

# -i 指定 interface 網路卡
> sudo tcpdump -i eth0
11:22:18.656009 ARP, Request who-has 192.168.43.1 tell lizhichengdembp, length 28
11:22:18.659657 ARP, Reply 192.168.43.1 is-at a6:44:d1:dd:ed:35 (oui Unknown), length 28

# 還可以使用表示式
> sudo tcpdump -i en0 '(dst 192.168.43.1 and src 192.168.43.184)or(dst 192.168.43.184 and src 192.168.43.1)'

6.2 Linux訪問DNS服務

6.2.1 host 命令

# 查詢 www.baidu.com 的A記錄
> host -t A www.baidu.com

6.2.2 tcpdump檢視DNS通許過程

# 在一個終端輸入
> sudo tcpdump -i en0 -nt -s 500 port domain
IP 192.168.43.184.63356 > 192.168.43.1.53: 48260+ A? www.baidu.com. (31)
IP 192.168.43.1.53 > 192.168.43.184.63356: 48260 3/5/5 CNAME www.a.shifen.com., A 183.232.231.173, A 183.232.231.172 (260)

# 在另一個終端中
> host -t A www.baidu.com
www.baidu.com is an alias for www.a.shifen.com.
www.a.shifen.com has address 183.232.231.173
www.a.shifen.com has address 183.232.231.172

6.3 檢視報文二進位制

# tcpdump的-x選項可以做到
> sudo tcpdump -ntx -i lo0

然後使用 ping或者telnet本地

6.4 IP分片與tcpdump只抓取ICMP

# 只抓取ICMP 注意offset偏移,第二個資料包的offset是第一個資料包的length;id是一樣的;flags[+]說明後面還有後續分片,flags[none]表示後續買有其他分片了。這裡的flag是ipv4報文頭部中3位標誌
> sudo tcpdump -ntv -i lo0 icmp
IP (tos 0x0, ttl 64, id 65515, offset 0, flags [+], proto ICMP (1), length 1500)
    192.168.43.184 > 192.168.43.1: ICMP echo request, id 14342, seq 0, length 1480
IP (tos 0x0, ttl 64, id 65515, offset 1480, flags [none], proto ICMP (1), length 21)
    192.168.43.184 > 192.168.43.1: ip-proto-1

# 指定長度 讓其炒股單個IP資料包限制長度,使其分片
> ping 127.0.0.1 -s 1473 -c 1

本文屬於個人讀書筆記,不正確的歡迎指正。後續會根據理解的加深而繼續完善

7. 其他

  • 也許有人回想起WebSocket。這個與socket又有什麼關係呢?WebSocket只是一個長的Http連線,一般用於聊天室

我的個人部落格:http://worthly.cn/

相關文章