【lwip】11-UDP协议&源码分析( 二 )

目的端口号:远端主机用户进程接收数据绑定的端口号 。
总长度:是UDP数据报的总长度:UDP首部+UDP数据区 。

  • 这个字段有点冗余,因为在IP报文中就包含了IP首部和IP总长度 , 这样能计算出UDP数据报的长度 。所以,UDP LITE就把这个字段改为需要进行校验和的UDP报文数据长度(从UDP首部算起) 。
  • 对于UDP LITE协议,这个字段为0时,表示对整个UDP报文进行校验和计算 。参考RFC 3828 chap. 3.1
  • 对于UDP LITE协议,这个字段要么为0 , 要么不少于UDP报文首部长度(即是校验和至少要涵盖UDP首部) 。参考RFC 3828 chap. 3.1
检验和:UDP协议为UDP伪首部+UDP首部+UDP数据区所有数据都加入校验和 。UDP LITE协议为“总长度”指定的长度加入校验和,从UDP伪首部算起,再加上伪首部校验和 。
  • 填入0时 , 表示不进行校验和 。而在实际计算校验和得到的结果刚好为0时,则向校验和字段填入0FFFF 。
    • 填入0XFFFF的可行性证明:如果校验和结果为0,即是其它数据的和为0XFFFF 。而对端继续校验和时,就是0XFFFF+0XFFFF,结果还是0XFFFF 。
UDP LITE:UDP协议的校验和是UDP首部和UDP数据区,如果数据区很多数据,一个校验失败就丢弃了,代价有点大,所以衍生出UDP LITE 。只校验UDP报文前面指定数据长度的数据 。一般用于实时适配、实时通话等这些要求通信速度快,可靠性要求不高的业务中 。
11.6 UDP伪首部和校验和UDP校验和的计算包括了三部分:UDP伪首部+UDP首部+UDP数据区 。
UDP伪首部包含IP首部一些字段 。其目的是让UDP验证数据是否已经正确到达目的地 。
UDP伪首部只参与校验,不参与实际发送 。
伪首部中UDP总长度和UDP首部的总长度字段一致 。
【lwip】11-UDP协议&源码分析

文章插图
11.7 wireshark报文分析
【lwip】11-UDP协议&源码分析

文章插图
11.8 UDP数据结构参考udp.cudp.h文件
11.8.1 UDP首部UDP首部长度:
#define UDP_HLEN 8UDP首部数据结构:
struct udp_hdr {PACK_STRUCT_FIELD(u16_t src); /* 源端口号 */PACK_STRUCT_FIELD(u16_t dest); /* 目的端口号 */PACK_STRUCT_FIELD(u16_t len); /* 总长度 */PACK_STRUCT_FIELD(u16_t chksum); /* 校验和 */} PACK_STRUCT_STRUCT;11.9 UDP控制块UDP控制块是整个UDP协议实现的核心部分 。
LWIP使用UDP控制块来描述一个UDP连接的所有相关信息 , 包括源端口号、目的端口号、源IP、目的IP等等 。
LWIP为每个UDP连接都分配一个UDP控制块,并用链表udp_pcbs链起来 。
但是LWIP也给UDP控制块数量设限制,MEMP_NUM_UDP_PCB为UDP控制块的内存池数量 。该宏缺省为8 。
UDP控制块数据结构:
#if LWIP_NETIF_USE_HINTS#define IP_PCB_NETIFHINT ;struct netif_hint netif_hints#else /* LWIP_NETIF_USE_HINTS */#define IP_PCB_NETIFHINT#endif /* LWIP_NETIF_USE_HINTS *//* This is the common part of all PCB types. It needs to be at thebeginning of a PCB type definition. It is located here so thatchanges to this common part are made in one location instead ofhaving to change all PCB structs. */#define IP_PCB\/* 按网络字节顺序排列的IP地址 */ \ip_addr_t local_ip;\ip_addr_t remote_ip;\/* 绑定的netif的索引 */\u8_t netif_idx;\/* 套接口选项 */\u8_t so_options;\/* 服务类型 */\u8_t tos;\/* TTL */\u8_t ttl\/* 链路层地址解析提示 */ \IP_PCB_NETIFHINT/** the UDP protocol control block */struct udp_pcb {IP_PCB; /* UDP控制块和IP协议相关的字段 */struct udp_pcb *next; /* UDP控制块链表节点 */u8_t flags; /* 控制块状态 */u16_t local_port, remote_port; /* 本地端口号和远端端口号 */#if LWIP_MULTICAST_TX_OPTIONS /* 支持组播相关 */#if LWIP_IPV4/* 组播数据包的出网络接口,通过IPv4地址(如果没有'any') */ip4_addr_t mcast_ip4;#endif /* LWIP_IPV4 *//* 组播数据包的出网络接口,根据接口索引(如果非零) */u8_t mcast_ifindex;/* 发送数据时 , 组播报文的TTL值 */u8_t mcast_ttl;#endif /* LWIP_MULTICAST_TX_OPTIONS */#if LWIP_UDPLITE /* 支持UDP LITE */u16_t chksum_len_rx, chksum_len_tx; /* 接收、发送数据时需要进行校验的数据长度 */#endif /* LWIP_UDPLITE *//* 接收回调函数 */udp_recv_fn recv;/* 接收回调函数参数 */void *recv_arg;};11.10 端口号相关11.10.1 端口号范围#define UDP_LOCAL_PORT_RANGE_START0xc000#define UDP_LOCAL_PORT_RANGE_END0xffff#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & (u16_t)~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START))11.10.2 端口号初始值UDP的端口号由全局值

推荐阅读