一、根据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_SECONDstatic 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等全面诊断网络问题。