《TCP/IP詳解卷2:實現》筆記--UDP:用戶數據報協議

用戶數據報協議,即UDP,是一個面向數據報的簡單運輸層協議:進程的每次輸出操作只產生一個UDP數據報,從而發送

一個IP數據報。

進程通過創建一個Internet域內的SOCK_DGRAM類型的插口,來訪問UDP。該類型插口默認地稱爲無連接的。每次進程發送

數據時,必須指定目的IP地址和端口號。每次從插口上接收數據報時,進程可以從數據報中收到源IP地址和端口號。

UDP插口也可以被連接到一個特殊的IP地址和端口,這樣,所有寫到該插口的數據報都被髮往該目的地,而且只有來自該IP

地址和端口號的數據才被傳給該進程。


1.UDP的protosw結構

下圖顯示了UDP的協議交換入口



2.UDP的首部

UDP首部定義成一個udphdr結構,下圖是UDP首部的數據結構和圖。



在代碼中,通常把udp首部作爲一個緊跟着UDP首部的IP首部來引用。這就是udp_input如何處理收到的ip數據報,以及

udp_output如何構造外出的ip數據報,這種聯合的ip/udp首部是一個udpiphdr結構,如下圖所示:


20個字節的ip首部定義成一個ipovly結構,如下圖所示。不幸的是,這個結構並不是一個真正的ip首部,大小雖然相同,但是

字段不同。



3.udp_init函數

domaininit函數在系統初始化時調用udp的初始化函數(udp_init),這個函數所做的唯一的工作是把頭部PCB的向前和向

後指針指向它自己。這是一個雙向鏈表。

udb PCB的其他部分都被初始化爲0,儘管在這個頭部PCB中唯一使用的字段是inp_lport,它是要分配的下一個UDP臨時

端口號。


4.udp_output函數

當應用程序調用一下五個寫函數中的任意一個時,發生UDP輸出。這五個函數是:send,sendto或sendmsg、write或

writev。如果插口已經連接上,則可任意調用調用這五個函數,儘管用sendto或sendmsg不能指定目的地址。如果插口

還沒有連接上,則只能調用sendto和sendmsg,並且必須指定一個目的地址。下圖總結了這五個函數,它們在終止時,

都調用udp_output,該函數再調用ip_output。


五個函數終止調用sosend,並把一個指向msghdr結構的指針作爲參數傳給該函數。要輸出的數據被分裝在一個mbuf鏈

上,sosend把一個可選的目標地址和可選的控制信息放在mbuf中,併發布PRU_SEND請求。

udp_output函數的處理流程如下:

1.丟掉可選控制信息。udp輸出不適用任何控制信息。

2.臨時連接一個未連接上的接口。如果調用方爲UDP數據報指定了目的地址,則插口是由in_pcbconnect臨時連接到該地址

的,並在該函數的最後被斷連。

3.在前面加上ip/udp首部。M_PREPEND在數據的前面爲IP和UDP首部分配空間。


4.1.UDP檢驗和計算和僞首部

在討論udp_output的後一部分之前,我們描述一下udp如何填充ip/udp首部的某些字段,如何計算udp檢驗和,如何傳遞

ip/udp首部及數據給ip輸出的,這些工作很巧妙地使用了ipovly結構。

下圖顯示了udp_output在由m指向的mbuf鏈的第一個存儲器上構造的28字節ip/udp首部。沒有陰影的字段是udp_output

填充的,有陰影的字段是由ip_output填充的。



在計算UDP檢驗和使用以下三個事實:1.在僞首部中(如下圖)的第三個32bit字看起來與ip首部中的第三個32bit字類似:

2個8bit值和一個16bit值。2.僞首部中的三個32bit值的順序是無關的。事實上,internet檢驗和的計算不依賴於所使用的

16bit值的順序。3.在檢驗和計算中另外再加上一個全0的32bit字沒有任何影響。


udp_output利用這三個事實,填充udpiphdr結構的字段,如下圖所示。


在20字節的ip首部中,最後三個32bit字被用作檢驗和計算的爲首部,ip首部的前兩個32bit字也用作檢驗和計算中,但他們

被初始化爲0,不影響最後的檢驗和。

下圖總結了我們描述的操作:


1.上圖中最上面的圖是爲首部的協議定義。

2.中間的圖是源代碼中使用的udpiphdr結構,被用於計算udp檢驗和。

3.下面的圖是出現在線路上的ip/udp首部。上面有箭頭的7個字段是udp_output在檢驗和之前填充的,上面有星號的3個字段

是udp_output在檢驗和計算之後填充的,其他6個有陰影的字段是ip_output填充的。


下面是udp_output函數的後半部分。

1.爲檢驗和計算準備僞首部。

2.計算檢驗和

3.填充UDP長度、TTL和TOS。

4.發送數據報。調用ip_output發送數據報。

5.斷連臨時連接的插口。


5.udp_input函數

當ip在它的協議字段指定爲UDP的輸入隊列上收到一個IP數據報時,才發生UDP的輸入。IP通過協議交換表中的pr_input
函數調用udp_input。因爲ip的輸入是在軟件中斷級,所以udp_input也在這一級上執行。udp_input的目標是把udp數據報
放置在合適的插口緩存內,喚醒該插口上因輸入阻塞的所有進程。
對udp_input函數的討論分爲三個部分:
1.udp對收到的數據報完成一般性的確認。
2.處理目的地是單播地址的udp數據報:找到合適的pcb,把數據報放到插口的緩存內。
3.處理目的地是廣播或多播地址的udp數據報:必須把數據報提交給多個插口。

5.1.對收到的udp數據報的一般確認

1.丟棄IP選項。

2.驗證UDP長度。與UDP數據報相關的兩個長度是:IP首部的長度字段(ip_len)和UDP首部的長度字段(uh_ulen)。

比較這兩個長度,可能有三種可能性:

1)ip_len等於uh_ulen。這是通常情況。

2)ip_len大於uh_ulen。ip首部太大,如下圖所示。代碼相信兩個長度中小的那個,並從數據報的最後移走多餘的數據字節,

從mbuf鏈的最後截斷數據。


3)ip_len小於uh_ulen。當udp首部的長度給定時,ip數據報比可能的小,如下圖所示。這說明數據報有錯誤,必須丟棄,

沒有其他的選擇。


3.保存ip首部的備份,驗證udp的檢驗和。


5.2.分用單播數據報

假定數據報的目的地址是一個單播地址。

1.檢查“向後一個”高速緩存。udp維護一個指針,該指針指向最後在其上接收數據報的internet pcb,在查看pcb之前,可能必須

搜索udp表上的pcb,把最近一次接收pcb的外部和本地地址以及端口號和收到的數據報進行比較。這稱爲“向後一個”高速緩存。

它是根據這樣一個假設,即收到的數據報極有可能要發往上一個數據報發往的同一端口。

2.搜索所有的UDP的PCB。

3.生成ICMP端口不可達差錯。如果沒有找到匹配的PCB,UDP通常產生一個ICMP端口不可達差錯。

4.返回源站IP地址和源站端口。

5.處理IP_RECVDSTADDR插口選項。該選項把收到的UDP數據報中的目的IP地址作爲控制信息返回。

6.把數據加到插口的接收隊列中。


5.3.分用多播和廣播數據報

這些數據報被提交給匹配的所有插口,而不僅僅是一個插口。


6.udp_saveopt函數

如果進程指定了IP_RECVDSTADDR插口選項,則udp_input調用udp_saveopt,從收到的數據報中接收目的IP地址。


7.udp_ctlinput函數

當icmp_input收到一個ICMP差錯(目的主機不可達、參數問題、重定向、源站抑制和超時)時,調用相應協議的pr_ctlinput

函數。對於UDP,調用udp_cltinput。我們來看下對收到的ICMP所做的處理:

1.icmp_input把icmp類型和碼轉換成PRC_xxxx差錯碼。

2.把PRC_xxxx差錯碼傳給協議的控制輸入函數。

3.internet pcb協議(TCP和UDP)把PRC_xxx差錯碼映射到一個unix的errno值,這個值被返回給進程。


8.udp_usrreq函數

許多操作都要調用協議的用戶請求函數,在某個UDP插口上調用五個寫函數中的任意一個,都以請求PRU_SEND調用UDP

的用戶請求函數結束。下面討論該函數中各個請求。

1.PRU_ATTACH請求,來自socket系統調用,分配一個新的pcb,把它加到udp pcb表的前面,把插口結構和pcb連接在一起。

2.close系統調用發佈PRU_DETACH請求。從udp表中移走pcb,並釋放該pcb。

3.PRU_BIND請求完成綁定操作。

4.如果有PRU_LISTEN請求,則是無效的,只有面向連接的協議才使用它。

5.在一個udp應用程序中,客戶或服務器,可以調用connect,它發送CONNECT請求修改插口發送或接收的外部ip地址和端口號。

6.socketpair系統調用發佈PRU_CONNECT2請求。

8.對於UDP插口,有兩種情況會產生PRU_DISCONNECT請求:

a.當關閉了一個連接上的UDP插口時,在PRU_DETACH之前調用PRU_DISCONNECT。

10.調用無法寫函數,發佈PRU_SEND請求,最終調用udp_output發送該數據報。

12.PRU_SOCKADDR和PRU_PEERADDR請求分配來自系統調用getsockname和getpeername。


9.udp_sysctl函數

udp的sysctl函數只支持一個選項,udp檢驗和標誌位。系統管理員可以禁止用sysctl程序使能或靜止udp檢驗和。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章