UDP:用户数据报

来源:互联网 发布:诲女知之乎悔 编辑:程序博客网 时间:2024/05/16 05:45

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传输控制块

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct udp_sock {  
  2.     /* inet_sock has to be the first member */  
  3.     struct inet_sock inet;  
  4.     int      pending;   /* Any pending frames ? */  
  5.     unsigned int     corkflag;  /* Cork is required */  
  6.     __u16        encap_type;    /* Is this an Encapsulation socket? */  
  7.     /* 
  8.      * Following member retains the information to create a UDP header 
  9.      * when the socket is uncorked. 
  10.      */  
  11.     __u16        len;       /* total length of pending frames */  
  12.     /* 
  13.      * Fields specific to UDP-Lite. 
  14.      */  
  15.     __u16        pcslen;  
  16.     __u16        pcrlen;  
  17. /* indicator bits used by pcflag: */  
  18. #define UDPLITE_BIT      0x1        /* set by udplite proto init function */  
  19. #define UDPLITE_SEND_CC  0x2        /* set via udplite setsockopt         */  
  20. #define UDPLITE_RECV_CC  0x4        /* set via udplite setsocktopt        */  
  21.     __u8         pcflag;        /* marks socket as UDP-Lite if > 0    */  
  22.     __u8         unused[3];  
  23.     /* 
  24.      * For encapsulation sockets. 
  25.      */  
  26.     int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);  
  27. };  
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);

0 0
原创粉丝点击