动态

详情 返回 返回

Android C++系列:Linux網絡(三)協議格式 - 动态 详情

1. 數據包封裝

傳輸層及其以下的機制由內核提供,應用層由用户進程提供(後面將介紹如何使用 socket API編寫應用程序),應用程序對通訊數據的含義進行解釋,而傳輸層及其以下 處理通訊的細節,將數據從一台計算機通過一定的路徑發送到另一台計算機。應用層 數據通過協議棧發到網絡上時,每層協議都要加上一個數據首部(header),稱為封裝 (Encapsulation),如下圖所示

image.png

不同的協議層對數據包有不同的稱謂,在傳輸層叫做段(segment),在網絡層叫做數 據報(datagram),在鏈路層叫做幀(frame)。數據封裝成幀後發到傳輸介質上,到達目 的主機後每層協議再剝掉相應的首部,最後將應用層數據交給應用程序處理。

2. 以太網幀格式

其中的源地址和目的地址是指網卡的硬件地址(也叫MAC地址),長度是48位,是在網 卡出廠時固化的。用ifconfig命令看一下,“HWaddr 00:15:F2:14:9E:3F”部分就是硬件地 址。協議字段有三種值,分別對應IP、ARP、RARP。幀末尾是CRC校驗碼。
image.png

以太網幀中的數據長度規定最小46字節,最大1500字節,ARP和RARP數據包的長度不夠 46字節,要在後面補填充位。最大值1500稱為以太網的最大傳輸單元(MTU),不同的網絡 類型有不同的MTU,如果一個數據包從以太網路由到撥號鏈路上,數據包長度大於撥號鏈路 的MTU了,則需要對數據包進行分片(fragmentation)。ifconfig命令的輸出中也有“MTU: 1500”。注意,MTU這個概念指數據幀中有效載荷的最大長度,不包括幀首部的長度。

3. ARP數據包格式

在網絡通訊時,源主機的應用程序知道目的主機的IP地址和端口號,卻不知道目的主機 的硬件地址,而數據包首先是被網卡接收到再去處理上層協議的,如果接收到的數據包的 硬件地址與本機不符,則直接丟棄。因此在通訊前必須獲得目的主機的硬件地址。ARP協議 就起到這個作用。源主機發出ARP請求,詢問“IP地址是192.168.0.1的主機的硬件地址是多 少”,並將這個請求廣播到本地網段(以太網幀首部的硬件地址填FF:FF:FF:FF:FF:FF表示 廣播),目的主機接收到廣播的ARP請求,發現其中的IP地址與本機相符,則發送一個ARP應 答數據包給源主機,將自己的硬件地址填寫在應答包中。

每台主機都維護一個ARP緩存表,可以用arp -a命令查看。緩存表中的表項有過期時間 (一般為20分鐘),如果20分鐘內沒有再次使用某個表項,則該表項失效,下次還要發ARP 請求來獲得目的主機的硬件地址。想一想,為什麼表項要有過期時間而不是一直有效?

ARP數據報的格式如下所示

image.png

注意到源MAC地址、目的MAC地址在以太網首部和ARP請求中各出現一次,對於鏈路層為 以太網的情況是多餘的,但如果鏈路層是其它類型的網絡則有可能是必要的。硬件類型指鏈 路層網絡類型,1為以太網,協議類型指要轉換的地址類型,0x0800為IP地址,後面兩個地 址長度對於以太網地址和IP地址分別為6和4(字節),op字段為1表示ARP請求,op字段為2 表示ARP應答。

下面舉一個具體的例子。 請求幀如下(為了清晰在每行的前面加了字節計數,每行16個字節): 以太網首部(14字節)

0000: ffffffffffff00055d6158a80806

ARP幀(28字節)

0000: 00 01

0010: 08000604000100055d6158a8c0a80037

0020: 000000000000c0a80002

填充位(18字節)

0020: 00 77 31 d2 50 10

0030: fd7841d30000000000000000

以太網首部:目的主機採用廣播地址,源主機的MAC地址是00:05:5d:61:58:a8,上層協議類型0x0806表示ARP。

ARP幀:硬件類型0x0001表示以太網,協議類型0x0800表示IP協議,硬件地址(MAC地址)長度為6,協議地址(IP地址)長度為4,op為0x0001表示請求目的主機的MAC地址,源 主機MAC地址為00:05:5d:61:58:a8,源主機IP地址為c0 a8 00 37(192.168.0.55),目的 主機MAC地址全0待填寫,目的主機IP地址為c0 a8 00 02(192.168.0.2)。

由於以太網規定最小數據長度為46字節,ARP幀長度只有28字節,因此有18字節填充 位,填充位的內容沒有定義,與具體實現相關。

應答幀如下:

以太網首部

0000: 00055d6158a800055da1b8400806

ARP幀

0000: 00 01

0010: 08000604000200055da1b840c0a80002

0020: 00055d6158a8c0a80037

填充位

0020: 00 77 31 d2 50 10

0030: fd7841d30000000000000000

以太網首部:目的主機的MAC地址是00:05:5d:61:58:a8,源主機的MAC地址是00:05:5d:a1:b8:40,上層協議類型0x0806表示ARP。

ARP幀:硬件類型0x0001表示以太網,協議類型0x0800表示IP協議,硬件地址(MAC地址)長度為6,協議地址(IP地址)長度為4,op為0x0002表示應答,源主機MAC地址為 00:05:5d:a1:b8:40,源主機IP地址為c0 a8 00 02(192.168.0.2),目的主機MAC地址為 00:05:5d:61:58:a8,目的主機IP地址為c0 a8 00 37(192.168.0.55)。

如果源主機和目的主機不在同一網段,ARP請求的廣播幀無法穿過路由器,源 主機如何與目的主機通信?

4. IP段格式

image.png

IP數據報的首部長度和數據長度都是可變長的,但總是4字節的整數倍。對於IPv4,4 位版本字段是4。4位首部長度的數值是以4字節為單位的,最小值為5,也就是説首部長度 最小是4x5=20字節,也就是不帶任何選項的IP首部,4位能表示的最大值是15,也就是説首 部長度最大是60字節。8位TOS字段有3個位用來指定IP數據報的優先級(目前已經廢棄不 用),還有4個位表示可選的服務類型(最小延遲、最大吐量、最大可靠性、最小成本), 還有一個位總是0。總長度是整個數據報(包括IP首部和IP層payload)的字節數。每傳一 個IP數據報,16位的標識加1,可用於分片和重新組裝數據報。3位標誌和13位片偏移用於 分片。TTL(Time to live)是這樣用的:源主機為數據包設定一個生存時間,比如64,每過 一個路由器就把該值減1,如果減到0就表示路由已經太長了仍然找不到目的主機的網絡, 就丟棄該包,因此這個生存時間的單位不是秒,而是跳(hop)。協議字段指示上層協議 是TCP、UDP、ICMP還是IGMP。然後是校驗和,只校驗IP首部,數據的校驗由更高層協議負 責。IPv4的IP地址長度為32位。選項字段的解釋從略。

想一想,前面講了以太網幀中的最小數據長度為46字節,不足46字節的要用填充字節補 上,那麼如何界定這46字節裏前多少個字節是IP、ARP或RARP數據報而後面是填充字節?

5. UDP數據包格式

image.png

下面分析一幀基於UDP的TFTP協議幀。

以太網首部

0000: 00055d67d0b100055d6158a80800

IP首部

0000: 45 00

0010: 005393250000801125ecc0a80037c0a8

0020: 00 01

UDP首部

0020: 05 d4 00 45 00 3f ac 40

TFTP協議

0020: 00 01 ‘c”:‘”’q’

0030: ‘w’ ‘e’ ‘r’ ‘q”.‘’q’‘ w’ ‘e’ 00 ’n’ ‘e‘ ’t’ ‘a‘ ’s’ ‘c’ ‘i’

0040: ‘i’ 00 ’b’ ‘l’ ‘k‘ ’s’ ‘i’ ‘z’ ‘e’ 00 ’5’ ‘1’ ‘2’ 00 ’t’ ‘i’

0050: ’m’ ‘e’ ‘o’ ‘u‘ ’t’ 00 ‘1’ ‘0’ 00 ’t‘ ’s’ ‘i’ ‘z’ ‘e’ 00 ’0’

0060: 00

以太網首部:源MAC地址是00:05:5d:61:58:a8,目的MAC地址是00:05:5d:67:d0:b1,上層協議類型0x0800表示IP。

IP首部:每一個字節0x45包含4位版本號和4位首部長度,版本號為4,即IPv4,首部長度為5,説明IP首部不帶有選項字段。服務類型為0,沒有使用服務。16位總長度字段(包 括IP首部和IP層payload的長度)為0x0053,即83字節,加上以太網首部14字節可知整個幀長度是97字節。IP報標識是0x9325,標誌字段和片偏移字段設置為0x0000,就是DF=0允許分 片,MF=0此數據報沒有更多分片,沒有分片偏移。TTL是0x80,也就是128。上層協議0x11表 示UDP協議。IP首部校驗和為0x25ec,源主機IP是c0 a8 00 37(192.168.0.55),目的主機 IP是c0 a8 00 01(192.168.0.1)。

UDP首部:源端口號0x05d4(1492)是客户端的端口號,目的端口號0x0045(69)是 TFTP服務的well-known端口號。UDP報長度為0x003f,即63字節,包括UDP首部和UDP層pay- load的長度。UDP首部和UDP層payload的校驗和為0xac40。

TFTP是基於文本的協議,各字段之間用字節0分隔,開頭的00 01表示請求讀取一個文 件,接下來的各字段是:

c:\qwerq.qwe 
netascii 
blksize 512 
timeout 10 
tsize 0

一般的網絡通信都是像TFTP協議這樣,通信的雙方分別是客户端和服務器,客户端主動 發起請求(上面的例子就是客户端發起的請求幀),而服務器被動地等待、接收和應答請 求。客户端的IP地址和端口號唯一標識了該主機上的TFTP客户端進程,服務器的IP地址和端 口號唯一標識了該主機上的TFTP服務進程,由於客户端是主動發起請求的一方,它必須知道 服務器的IP地址和TFTP服務進程的端口號,所以,一些常見的網絡協議有默認的服務器端 口,例如HTTP服務默認TCP協議的80端口,FTP服務默認TCP協議的21端口,TFTP服務默認UDP 協議的69端口(如上例所示)。在使用客户端程序時,必須指定服務器的主機名或IP地址, 如果不明確指定端口號則採用默認端口,請讀者查閲ftp、tftp等程序的man page瞭解如何 指定端口號。/etc/services中列出了所有well-known的服務端口和對應的傳輸層協議,這 是由IANA(Internet Assigned Numbers Authority)規定的,其中有些服務既可以用TCP也 可以用UDP,為了清晰,IANA規定這樣的服務採用相同的TCP或UDP默認端口號,而另外一些 TCP和UDP的相同端口號卻對應不同的服務。

很多服務有well-known的端口號,然而客户端程序的端口號卻不必是well-known的, 往往是每次運行客户端程序時由系統自動分配一個空閒的端口號,用完就釋放掉,稱為 ephemeral的端口號,想想這是為什麼。

前面提過,UDP協議不面向連接,也不保證傳輸的可靠性,例如:

發送端的UDP協議層只管把應用層傳來的數據封裝成段交給IP協議層就算完成任務了, 如果因為網絡故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤信息。

接收端的UDP協議層只管把收到的數據根據端口號交給相應的應用程序就算完成任務 了,如果發送端發來多個數據包並且在網絡上經過不同的路由,到達接收端時順序已經錯亂 了,UDP協議層也不保證按發送時的順序交給應用層。

通常接收端的UDP協議層將收到的數據放在一個固定大小的緩衝區中等待應用程序來提 取和處理,如果應用程序提取和處理的速度很慢,而發送端發送的速度很快,就會丟失數據 包,UDP協議層並不報告這種錯誤。

因此,使用UDP協議的應用程序必須考慮到這些可能的問題並實現適當的解決方案,例 如等待應答、超時重發、為數據包編號、流量控制等。一般使用UDP協議的應用程序實現都 比較簡單,只是發送一些對可靠性要求不高的消息,而不發送大量的數據。例如,基於UDP 的TFTP協議一般只用於傳送小文件(所以才叫trivial的ftp),而基於TCP的FTP協議適用於 各種文件的傳輸。下面看TCP協議如何用面向連接的服務來代替應用程序解決傳輸的可靠性問題。

6. TCP數據報格式

image.png

和UDP協議一樣也有源端口號和目的端口號,通訊的雙方由IP地址和端口號標識。32位 序號、32位確認序號、窗口大小稍後詳細解釋。4位首部長度和IP協議頭類似,表示TCP協 議頭的長度,以4字節為單位,因此TCP協議頭最長可以是4x15=60字節,如果沒有選項字 段,TCP協議頭最短20字節。URG、ACK、PSH、RST、SYN、FIN是六個控制位,本節稍後將解 釋SYN、ACK、FIN、RST四個位,其它位的解釋從略。16位檢驗和將TCP協議頭和數據都計算 在內。緊急指針和各種選項的解釋從略。

通信時序

下圖是一次TCP通訊的時序圖。
image.png

在這個例子中,首先客户端主動發起連接、發送請求,然後服務器端響應請求,然後客户端主動關閉連接。兩條豎線表示通訊的兩端,從上到下表示時間的先後順序,注意,數據從一端傳到網絡的另一端也需要時間,所以圖中的箭頭都是斜的。雙方發送的段按時間順 序編號為1-10,各段中的主要信息在箭頭上標出,例如段2的箭頭上標着SYN, 8000(0), ACK 1001, ,表示該段中的SYN位置1,32位序號是8000,該段不攜帶有效載荷(數據字節數為 0),ACK位置1,32位確認序號是1001,帶有一個mss選項值為1024。

建立連接的過程:

  1. 客户端發出段1,SYN位表示連接請求。序號是1000,這個序號在網絡通訊中用作臨時 的地址,每發一個數據字節,這個序號要加1,這樣在接收端可以根據序號排出數據包的正 確順序,也可以發現丟包的情況,另外,規定SYN位和FIN位也要佔一個序號,這次雖然沒發 數據,但是由於發了SYN位,因此下次再發送應該用序號1001。mss表示最大段尺寸,如果一 個段太大,封裝成幀後超過了鏈路層的最大幀長度,就必須在IP層分片,為了避免這種情 況,客户端聲明自己的最大段尺寸,建議服務器端發來的段不要超過這個長度。
  2. 服務器發出段2,也帶有SYN位,同時置ACK位表示確認,確認序號是1001,表示“我 接收到序號1000及其以前所有的段,請你下次發送序號為1001的段”,也就是應答了客户端 的連接請求,同時也給客户端發出一個連接請求,同時聲明最大尺寸為1024。
  3. 客户端發出段3,對服務器的連接請求進行應答,確認序號是8001。

在這個過程中,客户端和服務器分別給對方發了連接請求,也應答了對方的連接請求, 其中服務器的請求和應答在一個段中發出,因此一共有三個段用於建立連接,稱為’‘’三 方握手(three-way-handshake)”’。在建立連接的同時,雙方協商了一些信息,例如雙方發送序號的初始值、最大段尺寸等。

在TCP通訊中,如果一方收到另一方發來的段,讀出其中的目的端口號,發現本機並沒 有任何進程使用這個端口,就會應答一個包含RST位的段給另一方。

數據傳輸的過程:

  1. 客户端發出段4,包含從序號1001開始的20個字節數據。
  2. 服務器發出段5,確認序號為1021,對序號為1001-1020的數據表示確認收到,同時請求發送序號1021開始的數據,服務器在應答的同時也向客户端發送從序號8001開始的10個字 節數據,這稱為piggyback。
  3. 客户端發出段6,對服務器發來的序號為8001-8010的數據表示確認收到,請求發送序 號8011開始的數據。

關閉連接的過程:

  1. 客户端發出段7,FIN位表示關閉連接的請求。
  2. 服務器發出段8,應答客户端的關閉連接請求。
  3. 服務器發出段9,其中也包含FIN位,向客户端發送關閉連接請求。
  4. 客户端發出段10,應答服務器的關閉連接請求。

7. 總結

本文介紹了網絡協議格式:數據包封裝、以太網幀格式、ARP數據包格式、IP段格式、UDP數據包格式、TCP數據包格式等。

user avatar daniusdk 头像 hejing-michael 头像 youqingyouyidedalianmao 头像 kindledawn 头像 tong_6816038415d24 头像 waluna 头像 zhuweitao 头像 maomaotou 头像 hnclou 头像 fkcaikengren 头像 aitechshare 头像 wunima 头像
点赞 20 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.