目录
UDP 是一个简单的数据报的传输层协议:应用线程的每个输出数据都正好产生一个UDP 数据报,并组装成一份待发送的 IP 数据报。
1. UDP 协议简介
UDP 是User Datagram Protocol 的简称, 中文名是用户数据报协议,是一种无连接、不可靠的协议,它只是简单地实现从一端主机到另一端主机的数据传输功能,这些数据通过IP 层发送,在网络中传输,到达目标主机的顺序是无法预知的,因此需要应用程序对这些数据进行排序处理,这就带来了很大的不方便,此外,UDP 协议更没有流量控制、拥塞控制等功能,在发送的一端,UDP 只是把上层应用的数据封装到UDP 报文中,在差错检测方面,仅仅是对数据进行了简单的校验,然后将其封装到IP 数据报中发送出去。而在接收端,无论是否收到数据,它都不会产生一个应答发送给源主机,并且如果接收到数据发送校验错误,那么接收端就会丢弃该UDP 报文,也不会告诉源主机,这样子传输的数据是无法保障其准确性的,如果想要其准确性,那么就需要应用程序来保障了。
UDP 协议的特点:
1. 无连接、不可靠。
2. 尽可能提供交付数据服务,出现差错直接丢弃,无反馈。
3. 面向报文,发送方的UDP 拿到上层数据直接添加个UDP 首部,然后进行校验后就递交给IP 层,而接收的一方在接收到UDP 报文后简单进行校验,然后直接去除数据递交给上层应用。
4. 支持一对一,一对多,多对一,多对多的交互通信。
5. 速度快,UDP 没有TCP 的握手、确认、窗口、重传、拥塞控制等机制,UDP 是一个无状态的传输协议,所以它在传递数据时非常快,即使在网络拥塞的时候UDP 也不会降低发送的数据。
UDP 虽然有很多缺点,但是也不排除其能用于很多场合,因为在如今的网络环境下,UDP 协议传输出现错误的概率是很小的,并且它的实时性是非常好,常用于实时视频的传输,比如直播、网络电话等,因为即使是出现了数据丢失的情况,导致视频卡帧,这也不是什么大不了的事情,所以,UDP 协议还是会被应用与对传输速度有要求,并且可以容忍出现差错的数据传输中。
2. UDP 常用端口号
UDP 报文协议根据对应的端口号传递到目标主机的应用线程,同样的,传输层到应用层的唯一标识是通过端口号决定的,两个线程之间进行通信必须用端口号进行识别,同样的使用“IP 地址+端口号”来区分主机不同的线程。
3. UDP 报文
UDP 报文也被称为用户数据报,与TCP 协议一样,由报文首部与数据区域组成。在UDP 协议中,它只是简单将应用层的数据进行封装(添加一个UDP 报文首部),然后传递到IP 层,再通过网卡发送出去,因此,UDP 数据也是经过两次封装.
关于源端口号、目标端口号与校验和字段的作用与TCP 报文段一样,端口号的取值在0~65535 之间;16bit 的总长度用于记录UDP 报文的总长度,包括8 字节的首部长度与数据区域。
4. UDP 报文的数据结构
4.1 UDP 报文首部结构体
LwIP 定义了一个UDP 报文首部数据结构,名字叫udp_hdr,是一个结构体,它定义了UDP 报文首部的各个字段。
PACK_STRUCT_BEGIN
struct udp_hdr {
PACK_STRUCT_FIELD(u16_t src);
PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */
PACK_STRUCT_FIELD(u16_t len);
PACK_STRUCT_FIELD(u16_t chksum);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
4.2 UDP 控制块
LwIP 定义了一个UDP 控制块,记录与UDP 通信的所有信息,如源端口号、目标端口号、源IP 地址、目标IP 地址以及收到数据时候的回调函数等等,系统会为每一个基于UDP 协议的应用线程创建一个UDP 控制块,并且将其与对应的端口绑定,这样子就能进行UDP 通信了。与TCP 协议一样,LwIP 会把多个这样子的UDP 控制块用一个链表连接起来,在处理的时候遍历列表,然后对控制块进行操作。
/** the UDP protocol control block */
struct udp_pcb {
/** Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct udp_pcb *next;
u8_t flags;
/** ports are in host byte order */
u16_t local_port, remote_port;
#if LWIP_MULTICAST_TX_OPTIONS
#if LWIP_IPV4
/** outgoing network interface for multicast packets, by IPv4 address (if not 'any') */
ip4_addr_t mcast_ip4;
#endif /* LWIP_IPV4 */
/** outgoing network interface for multicast packets, by interface index (if nonzero) */
u8_t mcast_ifind