Linux C高階程式設計——網路程式設計之UDP(4)
Linux網路程式設計——UDP
宗旨:技術的學習是有限的,分享的精神是無限的。
下面分析一幀基於UDP的TFTP協議幀。
乙太網首部
0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00
IP首部0000: 45 00
0010: 00 53 93 25 00 00 80 11 25 ec c0 a8 00 37 c0 a8
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此資料報沒有更多分片,沒有分片偏移。
UDP首部:源埠號0x05d4( 1492)是客戶端的埠號,目的埠號0x0045( 69)是TFTP服務的well-known埠號。 UDP報長度為0x003f,即63位元組,包括UDP首部和UDP層payload的長度。 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中列出了所有wellknown的服務埠和對應的傳輸層協議,這是由IANA( Internet Assigned Numbers Authority)規定的,其中有些服務既可以用TCP也可以用UDP,為了清晰, IANA規定這樣的服務採用相同的TCP或UDP預設埠號,而另外一些TCP和UDP的相同埠號卻對應不同的服務。
UDP協議不面向連線,也不保證傳輸的可靠性,例如:
傳送端的UDP協議層只管把應用層傳來的資料封裝成段交給IP協議層就算完成任務了,如果因為網路故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤資訊。
接收端的UDP協議層只管把收到的資料根據埠號交給相應的應用程式就算完成任務了,如果傳送端發來多個數據包並且在網路上經過不同的路由,到達接收端時順序已經錯亂了,UDP協議層也不保證按傳送時的順序交給應用層。
通常接收端的UDP協議層將收到的資料放在一個固定大小的緩衝區中等待應用程式來提取和處理,如果應用程式提取和處理的速度很慢,而傳送端傳送的速度很快,就會丟失資料包, UDP協議層並不報告這種錯誤。