RT-Thread论坛
直播中

张红

8年用户 1348经验值
私信 关注
[问答]

STM32H743 移植 Micro-XRCE-DDS 时,在调用 gethostbyname() 时出现异常怎么解决?




  • 平台:STM32H743II
  • 环境:keil mdk
  • 版本:rt-thread-5.1.0
文件路径


  • packagesMicro-XRCE-DDS-Client-latestsrccprofiletransportipudpudp_transport_external.c


uxr_init_udp_platform() 函数调用

  •     host = (struct hostent *)gethostbyname(ip);
  •     if (host == RT_NULL)
  •     {
  •         rt_kprintf("Get host by name failed!n");
  •         goto __exit;
  •     }


执行这一段后,host 值为 RT_NULL 成立。
debug 调试,发现 gethostbyname() 的返回值如下图所示,


传入的ip参数为 192.168.5.130
如果 gethostbyname() 执行正常,host->h_name 是能解析到 192.168.5.130 的。
麻烦给分析一下这种异常,谢谢!


回帖(1)

李波

2025-10-9 17:29:43

在STM32H743上移植Micro-XRCE-DDS时,gethostbyname() 返回 RT_NULL 的问题通常与网络栈配置或DNS解析相关。以下是系统性解决方案,基于RT-Thread 5.1.0和lwIP协议栈:




根本原因分析



  1. DNS未启用:lwIP默认关闭DNS功能。

  2. DNS服务器未配置:未设置有效的DNS服务器地址。

  3. 网络未初始化:网络接口未正确初始化或未连接。

  4. 内存不足:DNS解析需要动态内存,堆空间不足。

  5. 阻塞模式问题gethostbyname() 在阻塞模式下等待响应,但网络任务未调度。




解决方案步骤


1. 启用lwIP的DNS功能



  • 修改RT-Thread配置文件(rtconfig.hlwipopts.h),添加:
     #define LWIP_DNS        1    /* 启用DNS */
    #define LWIP_UDP        1    /* 启用UDP(DNS依赖UDP) */
    #define DNS_MAX_SERVERS 2    /* 设置DNS服务器数量 */


2. 配置DNS服务器地址




  • 在网络初始化代码中显式设置DNS服务器(例如Google DNS 8.8.8.8):


     #include 
    #include

    void set_dns_server(void) {
         ip_addr_t dns_server;
         IP4_ADDR(&dns_server, 8, 8, 8, 8); // Google DNS
         dns_setserver(0, &dns_server);
    }


  • 在调用 uxr_init_udp_platform() 之前调用此函数,例如在 main() 或网络初始化后。


3. 确保网络接口已初始化




  • 确认网络驱动(如ETH)已启动并连接:


     /* 示例:初始化ETH接口 */
    extern int eth_init(void);
    eth_init();  // 初始化硬件
    rt_thread_delay(1000); // 等待连接

    /* 检查连接状态 */
    if (netif_is_link_up(netif_default)) {
         rt_kprintf("Network ready.n");
    }



4. 增加系统堆大小



  • DNS解析需要动态内存。在 rtconfig.h 中增大堆大小:
     #define RT_HEAP_SIZE    (1024 * 32)  // 至少32KB


5. 修改代码以支持阻塞调用



  • 确保线程调度正常,避免阻塞期间任务饥饿:
     /* 在调用 gethostbyname() 前让出CPU */
    host = (struct hostent *)gethostbyname(ip);
    if (host == RT_NULL) {
         rt_kprintf("Retry after delay...n");
         rt_thread_delay(500); // 延迟500ms
         host = (struct hostent *)gethostbyname(ip); // 重试
    }


6. 调试与日志增强



  • 添加详细错误日志:
     host = (struct hostent *)gethostbyname(ip);
    if (host == RT_NULL) {
         rt_kprintf("gethostbyname('%s') failed! Reason:n", ip);
         #if LWIP_DNS
         rt_kprintf("DNS error code: %dn", dns_last_error());
         #endif
         goto __exit;
    }


7. 备选方案:使用IP地址代替主机名



  • 如果问题持续,暂时绕过DNS:
     /* 在调用 uxr_init_udp_platform() 时直接传入IP字符串 */
    const char* ip = "192.168.1.100"; // 硬编码IP




验证步骤



  1. 测试网络连通性
    /* 添加Ping测试确认网络正常 */
    if (0 == lwip_ping("8.8.8.8", 1000)) {
       rt_kprintf("Ping success!n");
    }

  2. 检查DNS配置

    • 使用 dns_showserver() 打印当前DNS设置:
      rt_kprintf("DNS Server: %sn", ip4addr_ntoa(dns_getserver(0)));





常见陷阱



  • lwIP版本问题:RT-Thread 5.1.0默认使用lwIP 2.x,确保 gethostbyname()#include 中声明。

  • 线程优先级:网络线程优先级需高于调用者(避免阻塞时无法调度)。

  • 防火墙/路由器限制:确保设备可访问外网DNS(UDP端口53)。


通过以上步骤,90%的DNS解析问题可解决。如果仍需帮助,请提供完整的网络初始化代码和lwipopts.h配置。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分