UDP:用戶數據報

    UDP是一個簡單的面向數據報的運輸層協議:進程的每個輸出操作通常會產生一個UDP數據報,並組裝成一份待發送的IP數據報。這與面向流的協議不同,如TCP,應用程序產生的數據與真正發送的單個IP數據報並不存在直接的關聯。

相關的協議參考tcp/ip協議學習筆記(7)UDP用戶數據報協議

UDP輸入和輸出以及輕量級UDP涉及以下文件:

include/net/udplite.h 定義輕量級UDP專用的函數等

include/linux/udp.h 定義UDP傳輸控制塊等

net/ipv4/udp.c UDP協議的實現

net/ipv4/udplite.c 輕量級UDP的實現

net/core/sock.c 實現傳輸層通用的函數

net/ipv4/datagram.c 實現UDP的connect調用

net/ipv4/af_inet.c 網絡層和傳輸層接口

UDP的輸入與輸出


UDP函數之間調用關係比TCP簡單的多,和TCP一樣,sock結構中的sk_receive_queue成員是UDP的接收隊列,通常情況下,接收到UDP數據報會緩存到此,等待用戶進程的讀取。UDP接收到數據報後的處理要比TCP簡單的多,通過校驗的UDP數據報,根據類型做不同的處理後被添加到接收隊列。

UDP傳輸控制塊

struct udp_sock {
	/* inet_sock has to be the first member */
	struct inet_sock inet;
	int		 pending;	/* Any pending frames ? */
	unsigned int	 corkflag;	/* Cork is required */
  	__u16		 encap_type;	/* Is this an Encapsulation socket? */
	/*
	 * Following member retains the information to create a UDP header
	 * when the socket is uncorked.
	 */
	__u16		 len;		/* total length of pending frames */
	/*
	 * Fields specific to UDP-Lite.
	 */
	__u16		 pcslen;
	__u16		 pcrlen;
/* indicator bits used by pcflag: */
#define UDPLITE_BIT      0x1  		/* set by udplite proto init function */
#define UDPLITE_SEND_CC  0x2  		/* set via udplite setsockopt         */
#define UDPLITE_RECV_CC  0x4		/* set via udplite setsocktopt        */
	__u8		 pcflag;        /* marks socket as UDP-Lite if > 0    */
	__u8		 unused[3];
	/*
	 * For encapsulation sockets.
	 */
	int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
};
struct inet_sock inet

udp_sock由inet_sock結構擴展而來

int pending

發送狀態,其值只能是0或AF_INET,0表示數據已經從UDP套接口發送到IP層,可以繼續調用sendmsg()發送數據,AF_INET表示UDP正在處理調用sendmsg()的發送數據,不需要處理目的地址、路由等信息,直接處理UDP數據

unsigned int corkflag

 0     有數據需要發送時,立即發送出去

非0    將UDP數據組成一個單一64KB的UDP數據報後將其發送出去,因此會有延遲
__u16 len

從UDP套接口發送數據到IP層時,標識待發送數據的長度

__u16pcslen
__u16   pcrlen

輕量級UDP,通過UDPLITE_SEND_CSCOV和UDPLITE_RECV_CSCOV選項設置,用於實現控制發送和接收校驗和的執行

 0     表示對發送/接收的整個UDP-Lite數據包進行校驗

>>=8   表示對發送/接收的UDP-Lite包的前pcslen/pcrlen個字節進行校驗

其他值是非法的

UDP的狀態

UDP的傳輸是沒有狀態的,但事實上,UDP和RAW也借用了TCP的一些值:在一個套接口創建之初,其狀態是TCP_CLOSE,當UDP套接口調用connect()後,狀態改變爲TCP_ESTABLISHED,最後,關閉套接口時又置回TCP_CLOSE,RAW也一樣。

輕量級UDP

2.6.20版本的Linux支持UDP-Lite。UDP-Lite協議相對較新,與UDP協議類似,但更適應網絡差錯率較大而應用對輕微差錯不敏感的情況,例如實時視頻播放等。那麼UDP-Lite與傳統的UDP有什麼不同呢?傳統的UDP協議對其負載(Payload)作完整的校驗,如果其中的哪怕只有一位發生了變化,那麼整個數據包就有可能被丟棄,在某些情況下,丟掉一個這樣的包代價是非常大的,尤其當數據包比較大的時候。在UDP-Lite協議中,一個數據包到底需不需對其負載進行校驗,或者是校驗多少位都是由用戶控制的,

Linux對UDP-Lite協議的支持也是通過在原來的UDP協議的基礎上添加了一個setsockopt選項來實現控制發送/接收 Checksum Coverage的

int val = 20;

setsockopt(s, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int));

int min = 20;

setsockopt(s, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &min, sizeof(int));

創建一個輕量級UDP套接口很簡單

s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);

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