一、根據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等全面診斷網絡問題。