udp_sendto_if()
:确定UDP本地IP地址,然后调用udp_sendto_if_src()
UDP发送数据基函数进行组包 。
struct udp_pcb *pcb
:负责本次发送的UDP控制块 。
struct pbuf *p
:需要发送的数据的pbuf 。
ip_addr_t *dst_ip
:远端IP地址 。
u16_t dst_port
:远端端口号地址 。
struct netif *netif
:指定发送UDP报文的网卡 。
- 参数校验 。
- 确定本地IP:
- 如果UDP控制块没有指定本地IP,则获取指定的网卡的IP作为UDP本地IP 。
- 如果UDP控制块指定了本地IP,则这个IP必须和指定网卡的IP一致,否则不发送 。
/** * @ingroup udp_raw * Send data to a specified address using UDP. * The netif used for sending can be specified. * * This function exists mainly for DHCP, to be able to send UDP packets * on a netif that is still down. * * @param pcb UDP PCB used to send the data. * @param p chain of pbuf's to be sent. * @param dst_ip Destination IP address. * @param dst_port Destination UDP port. * @param netif the netif used for sending. * * dst_ip & dst_port are expected to be in the same byte order as in the pcb. * * @return lwIP error code (@see udp_send for possible error codes) * * @see udp_disconnect() udp_send() */err_tudp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif){const ip_addr_t *src_ip;/* 参数校验 */LWIP_ERROR("udp_sendto_if: invalid pcb", pcb != NULL, return ERR_ARG);LWIP_ERROR("udp_sendto_if: invalid pbuf", p != NULL, return ERR_ARG);LWIP_ERROR("udp_sendto_if: invalid dst_ip", dst_ip != NULL, return ERR_ARG);LWIP_ERROR("udp_sendto_if: invalid netif", netif != NULL, return ERR_ARG);if (!IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) {return ERR_VAL;}/* PCB本地地址是IP_ANY_ADDR还是多播? */#if LWIP_IPV6if (IP_IS_V6(dst_ip)) {if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip)) ||ip6_addr_ismulticast(ip_2_ip6(&pcb->local_ip))) {src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip));if (src_ip == NULL) {/* 没有找到合适的源地址 */return ERR_RTE;}} else {/* 使用UDP PCB本地IPv6地址作为源地址,如果仍然有效 */if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) {/* 地址无效 */return ERR_RTE;}src_ip = &pcb->local_ip;}}#endif /* LWIP_IPV6 */#if LWIP_IPV4 && LWIP_IPV6else#endif /* LWIP_IPV4 && LWIP_IPV6 */#if LWIP_IPV4if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) ||ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) {/* 如果UDP控制块本地IP没有指定 , 或者指定的是多播地址,则使用指定的网卡的IP作为UDP本地IP即可 */src_ip = netif_ip_addr4(netif);} else { /**//* 检查UDP PCB本地IP地址是否正确 , 如果netif->ip_addr已更改 , 这可能是旧地址 */if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {/* UDP本地IP和指定网卡的IP不匹配,不发送 。*/return ERR_RTE;}/* 确认使用的源IP */src_ip = &pcb->local_ip;}#endif /* LWIP_IPV4 */#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDPreturn udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip);#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip);#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */}
11.13 UDP接收数据UDP接收处理数据,南向是通过udp_input()
API给IP层收到UDP数据报后上交到UDP协议处理 。udp_input()
:struct pbuf *p
:收到UDP报文的pbuf 。
struct netif *inp
:收到该UDP报文的网卡 。
- 参数校验 。
- 报文校验 。
- 匹配UDP PCB:通过IP和端口号确保该UDP报文得到某个应用程序 。遍历UDP PCB
udp_pcbs
:
- UDP PCB 本地端口、IP和UDP报文目的端口和IP匹配:端口一致且IP匹配:
- 当前UDP PCB没有指定本地IP , 或UDP报文的目的IP就是指向当前UDP PCB的IP 。本地可以匹配成功 。
- 如果UDP报文对应的目的IP是一个广播地址,且当前UDP设置了
SOF_BROADCAST
选项 。这个IP是全广播地址或者和当前UDP PCB IP处于同一个子网 。本地可以匹配成功 。 - 如果UDP PCB 本地端口、IP和UDP报文目的端口和IP匹配成功后,但是该UDP PCB还没有处于连接状态,则可以记录到
uncon_pcb
变量中 , 有更适合且未连接的UDP PCB适配本次UDP报文的,更新到uncon_pcb
中 。
- UDP PCB 远端端口、IP和UDP报文源端口和IP匹配:端口一致且IP匹配:
- UDP PCB远端IP随意或者就是当前UDP报文的源IP 。远端匹配成功 。
推荐阅读
- 【什么是妖股】妖股是什么意思
- .net 温故知新:【9】.NET日志记录 ILogger使用和原理
- 【k8s连载系列】2. k8s整体架构
- 安卓手机截屏模式怎么设置(手机截屏模式怎么设置)
- ubantu18.04@Intel 82545EM 【安装文档】TRex流量分析仪保姆级安装指南--基于VMware虚拟机
- 星之彼端丹铜事件该如何选择
- iphone怎么刷机(iphone刷机教程)
- 《正义联盟》中超人是怎么死的
- 王者荣耀娜可露露前尘镜中文语音包怎么设置
- 《三国演义》中曹操的大将许褚是怎么死的(三国许褚做了哪些大事)
- UDP PCB远端IP随意或者就是当前UDP报文的源IP 。远端匹配成功 。
- UDP PCB 本地端口、IP和UDP报文目的端口和IP匹配:端口一致且IP匹配: