STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断

c 复制代码
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判断

cpp 复制代码
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网络连接检测代码示例,用于检查设备是否成功连接互联网:

代码实现

c 复制代码
#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);

代码说明

  1. 代码创建了一个ICMP RAW socket用于发送和接收Ping包
  2. 使用Google的DNS服务器8.8.8.8作为Ping目标
  3. 实现了Ping的超时处理和响应接收
  4. 通过信号量同步Ping的发送和接收过程
  5. 结果会通过串口输出显示Ping是否成功

使用说明

  1. 在RT-Thread的env工具中确保已开启LwIP组件
  2. 将代码添加到项目中并编译
  3. 在FinSH命令行中执行ping_network命令
  4. 成功连接互联网时会显示"ping 8.8.8.8 success!"

注意事项

  1. 需要网络接口已正确初始化并能访问互联网
  2. 某些网络环境可能屏蔽ICMP包,这种情况下即使网络连通Ping也会失败
  3. 可以根据需要修改Ping的目标地址

常见问题处理

若ping命令不可用,需检查:

  • 网络协议栈(LwIP)是否正确初始化
  • 网络接口(如ETH或WIFI)是否正常连接
  • DNS配置是否正确(对于域名ping测试)

网络连接成功后,ping测试可作为基础的网络状态检测手段,配合其他网络工具如ifconfig、netstat等全面诊断网络问题。

相关推荐
链上Sniper12 分钟前
区块链架构深度解析:从 Genesis Block 到 Layer 2
开发语言·网络·架构·区块链·php
yzx99101314 分钟前
Python开发功能项目
服务器·开发语言·人工智能·python·深度学习
饭碗、碗碗香27 分钟前
【开发常用命令】:服务器与本地之间的数据传输
linux·运维·服务器·笔记·学习
JXNL@33 分钟前
STM32外设学习之串口
stm32·单片机·学习
森旺电子34 分钟前
stm32温湿度-超声波-LCD1602结合项目(Proteus仿真程序)
stm32·嵌入式硬件·proteus
woshihonghonga38 分钟前
STM32通用定时器TRC含义解析
stm32·单片机·嵌入式硬件
搬码临时工1 小时前
如何开启自己计算机远程桌面连接功能? 给别人或异地访问
运维·服务器·网络·远程工作
啃火龙果的兔子1 小时前
在服务器上使用 Docker 部署 Node.js 后端服务和前端项目
服务器·docker·node.js
勤奋的小王同学~1 小时前
(javaEE)网络原理-初识 局域网和广域网 ip地址和端口号 协议 五元组 协议分层 OSI七层模型 网络数据通信的基本流程
运维·服务器·网络
工程师0072 小时前
C#AES加密
网络·安全·web安全·c#