[应用相关] STM32+rt-thread判断是否联网

[复制链接]
318|1
 楼主| paotangsan 发表于 2025-7-10 22:01 | 显示全部楼层 |阅读模式
一、根据NETDEV_FLAG_INTERNET_UP位判断
static bool is_conncected(void)
{
    struct netdev *dev = RT_NULL;
    dev = netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);
    if (dev == RT_NULL)
    {
        printf("wait netdev internet up...");
        return false;
    }
    else
    {
        printf("local ip is:%d.%d.%d.%d", ((( dev->ip_addr.addr) >> 0) & 0xFF), ((( dev->ip_addr.addr) >> 8) & 0xFF),
                ((( dev->ip_addr.addr) >> 16) & 0xFF), ((( dev->ip_addr.addr) >> 24) & 0xFF));
        return true;
    }

}



二、如果开启dhcp根据是否获取到ip判断
bool is_connected()
{
        struct netdev *dev = RT_NULL;
        struct netif *netif = netif_list; // 获取第一个网络接口
        if (netif && netif_is_up(netif))
        { // 检查接口是否已初始化并启动
                struct dhcp *dhcp = netif_dhcp_data(netif); // 获取 DHCP 数据结构
                if (dhcp && dhcp->state == 10)
                { // 检查 DHCP 是否绑定到 IP 地址
                        log_i("network is connected and ip address is obtained!");
                        return true;
                }
                else
                {
                        log_w("network is up but no ip address!");
                        return false;
                }
        }
        else
        {
                log_w("network interface is not up!");
                return false;
        }
}



三、通过ping命令检测
以下是一个基于RT-Thread和LwIP的Ping网络连接检测代码示例,用于检查设备是否成功连接互联网:

代码实现
#include <rtthread.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include <lwip/icmp.h>
#include <lwip/inet.h>
#include <lwip/ip.h>

#define PING_DATA_SIZE       32
#define PING_DELAY           RT_TICK_PER_SECOND

static struct rt_semaphore ping_sem;
static rt_uint32_t ping_time;

static void ping_timeout(void *arg)
{
    rt_sem_release(&ping_sem);
}

static void ping_recv(int s, struct sockaddr_in *addr)
{
    char buf[64];
    int fromlen = sizeof(*addr);
    int len;

    while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0,
                                (struct sockaddr *)addr, (socklen_t *)&fromlen)) > 0)
    {
        struct ip_hdr *iphdr = (struct ip_hdr *)buf;
        struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));

        if (iecho->id == PING_ID && iecho->seqno == htons(ping_time))
        {
            rt_sem_release(&ping_sem);
            break;
        }
    }
}

static int ping(int s, const char *host)
{
    int timeout = PING_DELAY;
    struct sockaddr_in addr;
    struct hostent *hptr;
    struct rt_timer ping_timer;

    addr.sin_family = AF_INET;
    addr.sin_port = 0;

    if ((hptr = lwip_gethostbyname(host)) == NULL)
    {
        return -RT_ERROR;
    }

    addr.sin_addr.s_addr = *(rt_uint32_t *)hptr->h_addr_list[0];

    rt_timer_init(&ping_timer, "ping_timeout", ping_timeout, RT_NULL,
                  timeout, RT_TIMER_FLAG_ONE_SHOT);

    rt_timer_start(&ping_timer);
    rt_sem_init(&ping_sem, "ping_sem", 0, RT_IPC_FLAG_FIFO);

    for (ping_time = 0; ping_time < PING_DATA_SIZE; ping_time++)
    {
        struct icmp_echo_hdr *iecho;
        char buf[PING_DATA_SIZE + sizeof(struct icmp_echo_hdr)];

        iecho = (struct icmp_echo_hdr *)buf;
        ICMPH_TYPE_SET(iecho, ICMP_ECHO);
        ICMPH_CODE_SET(iecho, 0);
        iecho->chksum = 0;
        iecho->id = PING_ID;
        iecho->seqno = htons(ping_time);

        rt_memset(&buf[sizeof(struct icmp_echo_hdr)], 0x00, PING_DATA_SIZE);

        iecho->chksum = inet_chksum(iecho, sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE);

        if (lwip_sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&addr, sizeof(addr)) <= 0)
        {
            rt_timer_stop(&ping_timer);
            rt_sem_detach(&ping_sem);
            return -RT_ERROR;
        }

        if (rt_sem_take(&ping_sem, timeout) == RT_EOK)
        {
            rt_timer_stop(&ping_timer);
            rt_sem_detach(&ping_sem);
            return RT_EOK;
        }
    }

    rt_timer_stop(&ping_timer);
    rt_sem_detach(&ping_sem);
    return -RT_ERROR;
}

int ping_network(void)
{
    int s;
    int ret;

    s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
    if (s < 0)
    {
        rt_kprintf("create socket failed\n");
        return -1;
    }

    ret = ping(s, "8.8.8.8");  // Ping Google DNS服务器
    lwip_close(s);

    if (ret == RT_EOK)
    {
        rt_kprintf("ping 8.8.8.8 success!\n");
        return 0;
    }
    else
    {
        rt_kprintf("ping 8.8.8.8 failed!\n");
        return -1;
    }
}

MSH_CMD_EXPORT(ping_network, Ping test network connection);



代码说明
代码创建了一个ICMP RAW socket用于发送和接收Ping包
使用Google的DNS服务器8.8.8.8作为Ping目标
实现了Ping的超时处理和响应接收
通过信号量同步Ping的发送和接收过程
结果会通过串口输出显示Ping是否成功
使用说明
在RT-Thread的env工具中确保已开启LwIP组件
将代码添加到项目中并编译
在FinSH命令行中执行ping_network命令
成功连接互联网时会显示"ping 8.8.8.8 success!"
注意事项
需要网络接口已正确初始化并能访问互联网
某些网络环境可能屏蔽ICMP包,这种情况下即使网络连通Ping也会失败
可以根据需要修改Ping的目标地址
常见问题处理
若ping命令不可用,需检查:

网络协议栈(LwIP)是否正确初始化
网络接口(如ETH或WIFI)是否正常连接
DNS配置是否正确(对于域名ping测试)
网络连接成功后,ping测试可作为基础的网络状态检测手段,配合其他网络工具如ifconfig、netstat等全面诊断网络问题。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_15181569/article/details/148529050

小小蚂蚁举千斤 发表于 2025-7-28 23:04 | 显示全部楼层
判断是否联网很有必要
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

4323

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部