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

11.11.4 udp_bind_netif():绑定网卡udp控制块也可以绑定指定网卡 。
udp_bind_netif()

  • udp_pcb *pcb:需要绑定网卡的UDP控制块 。
  • struct netif *netif:UDP控制块需要绑定的网卡 。
    • 为NULL时 , 表示解绑 。
  • 获取网卡索引 , 绑定到UDP控制块 。
/** * @ingroup udp_raw * Bind an UDP PCB to a specific netif. * After calling this function, all packets received via this PCB * are guaranteed to have come in via the specified netif, and all * outgoing packets will go out via the specified netif. * * @param pcb UDP PCB to be bound. * @param netif netif to bind udp pcb to. Can be NULL. * * @see udp_disconnect() */voidudp_bind_netif(struct udp_pcb *pcb, const struct netif *netif){LWIP_ASSERT_CORE_LOCKED();if (netif != NULL) {pcb->netif_idx = netif_get_index(netif); /*获取网卡索引绑定到UDP控制块 */} else {pcb->netif_idx = NETIF_NO_INDEX; /* 取消绑定 */}}11.11.5 udp_connect():连接控制(本地行为)
UDP协议是没有连接状态的 , 但是为什么UDP可以调用udp_connect()这个函数?有什么用?
  • 调用这个是为了这个UDP控制块本地长期绑定一个远端IP和端口号,减少后面重复绑定和解绑的步骤 。
先了解下UDP sendto() 函数传输数据过程 :
  1. 第 1 阶段:向 UDP 控制块注册目标 IP 和端口号 。
  2. 第 2 阶段:传输数据 。
  3. 第 3 阶段:删除 UDP 控制块中注册的目标地址信息 。
如果需要频繁发送,那第一阶段和第三阶段是重复多余的,所以可以使用 已连接(connect)UDP 控制块 。
所以udp_connect()这个函数的目的是把UDP控制块注册长期目标IP和端口号 , 这样中途调用发送函数时 , 不需要重新注册和注销 。
可以使用udp_disconnect()进行注销 。
udp_connect()
  • struct udp_pcb *pcb:需要连接的UDP控制块 。
  • ip_addr_t *ipaddr:远端IP地址 。
  • u16_t port:远端端口号 。
  • 先检查有没有绑定了本地应用程序:即是UDP控制块有没有绑定了本地IP(包括任意IP)和本地端口号 。还没有绑定,则调用udp_bind()进行绑定 。
  • 注册远端IP和远端端口号 。
  • 标记当前UDP控制块状态为已连接状态 。
  • 确保当前UDP控制块已激活:即是是否插入了udp_pcbs链表 。还没插入就需要插入处理 。
/** * @ingroup udp_raw * Sets the remote end of the pcb. This function does not generate any * network traffic, but only sets the remote address of the pcb. * * @param pcb UDP PCB to be connected with remote address ipaddr and port. * @param ipaddr remote IP address to connect with. * @param port remote UDP port to connect with. * * @return lwIP error code * * ipaddr & port are expected to be in the same byte order as in the pcb. * * The udp pcb is bound to a random local port if not already bound. * * @see udp_disconnect() */err_tudp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port){struct udp_pcb *ipcb;LWIP_ASSERT_CORE_LOCKED(); /* 内核所内 */LWIP_ERROR("udp_connect: invalid pcb", pcb != NULL, return ERR_ARG);LWIP_ERROR("udp_connect: invalid ipaddr", ipaddr != NULL, return ERR_ARG);/* 确保已经绑定了本地端口号 */if (pcb->local_port == 0) { /* 本地端口号还没绑定 , 则需要先绑定 */err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);if (err != ERR_OK) {return err;}}/* 注册远端IP */ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);#if LWIP_IPV6 && LWIP_IPV6_SCOPES /* [lzm][test][可暂时跳过] *//* If the given IP address should have a zone but doesn't, assign one now,* using the bound address to make a more informed decision when possible. */if (IP_IS_V6(&pcb->remote_ip) &&ip6_addr_lacks_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNKNOWN)) {ip6_addr_select_zone(ip_2_ip6(&pcb->remote_ip), ip_2_ip6(&pcb->local_ip));}#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES *//* 注册远端端口号 */pcb->remote_port = port;/* UDP控制块状态标记上已连接(本地已连接) */pcb->flags |= UDP_FLAGS_CONNECTED;LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to "));ip_addr_debug_print_val(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,pcb->remote_ip);LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port));/* 检查下是否插入了udp_pcbs链表,如果没有插入,则需要插入处理 */for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {if (pcb == ipcb) {return ERR_OK;}}pcb->next = udp_pcbs;udp_pcbs = pcb;return ERR_OK;}11.11.6 udp_disconnect():断开连接(本地行为)

推荐阅读