当前位置: 代码网 > 服务器>服务器>Linux > Linux下实时获取WiFi与热点状态的方法详解

Linux下实时获取WiFi与热点状态的方法详解

2025年08月08日 Linux 我要评论
一、引言:为什么需要网络状态检测?1.1 典型应用场景在物联网和智能设备开发中,网络状态检测是基础而关键的功能。想象以下场景:智能家居:当家庭wifi断开时,智能音箱自动开启热点模式,让用户通过手机直

一、引言:为什么需要网络状态检测?

1.1 典型应用场景

在物联网和智能设备开发中,网络状态检测是基础而关键的功能。想象以下场景:

  • 智能家居:当家庭wifi断开时,智能音箱自动开启热点模式,让用户通过手机直连配置
  • 工业设备:生产线设备在检测到网络异常时,自动记录状态并开启维护通道
  • 移动终端:平板电脑在不同网络环境下自动调整同步策略,节省电量

1.2 技术实现目标

实现以下核心功能:

功能描述技术指标
wifi连接检测判断设备是否连接到无线网络响应时间<1s
wifi名称获取获取当前连接的无线网络ssid支持特殊字符
热点状态检测判断设备是否处于热点模式准确率100%
热点名称获取获取设备热点的ssid多编码支持

1.3 技术原理概述

linux系统通过networkmanager服务管理网络连接,提供了丰富的命令行工具:

  • iwgetid:查询无线接口连接状态
  • nmcli:networkmanager的命令行接口
  • hostapd:热点管理服务

qt的qprocess类可以无缝调用这些系统命令,并通过解析输出来获取网络状态信息。

二、核心思路:结合qt与linux命令

2.1 技术架构设计

2.2 关键命令分析

检测wifi连接状态

# 返回当前连接的ssid(无连接则返回空)
iwgetid -r

# 示例输出:
# myhomewifi

检测热点状态

# 查看活动连接中的热点
nmcli connection show --active | grep wifi | grep ap

# 查看hostapd进程
pgrep hostapd

获取热点名称

# 通过nmcli获取
nmcli device wifi show | grep ssid

# 通过hostapd配置获取
grep ssid= /etc/hostapd/hostapd.conf

2.3 性能考量

  • 命令执行时间:各命令在树莓派4上的平均执行时间
    • iwgetid:50-100ms
    • nmcli:200-300ms
    • pgrep:10-20ms
  • 优化策略
    • 缓存结果,减少命令调用
    • 异步执行,避免阻塞ui
    • 合理设置检测间隔(建议1-5秒)

三、详细实现:

3.1 核心类实现

networktool.h

#ifndef networktool_h
#define networktool_h

#include <qobject>
#include <qprocess>
#include <qtimer>

class networktool : public qobject
{
    q_object
public:
    explicit networktool(qobject *parent = nullptr);
    
    // 基础检测功能
    q_invokable bool iswificonnected();
    q_invokable qstring wifiname();
    q_invokable bool ishotspotactive();
    q_invokable qstring hotspotname();
    
    // 高级功能
    q_invokable void startautorefresh(int interval = 3000);
    q_invokable void stopautorefresh();
    
signals:
    void wifistatuschanged(bool connected, const qstring &name);
    void hotspotstatuschanged(bool active, const qstring &name);
    
private slots:
    void refreshstatus();
    
private:
    qstring executecommand(const qstring &cmd, const qstringlist &args = {});
    qstring parsewifiname(const qstring &output);
    qstring parsehotspotname(const qstring &output);
    
    qtimer m_refreshtimer;
    bool m_lastwifistate = false;
    qstring m_lastwifiname;
    bool m_lasthotspotstate = false;
    qstring m_lasthotspotname;
};

#endif // networktool_h

networktool.cpp

#include "networktool.h"
#include <qdebug>
#include <qfile>

networktool::networktool(qobject *parent) : qobject(parent)
{
    m_refreshtimer.setsingleshot(false);
    connect(&m_refreshtimer, &qtimer::timeout, this, &networktool::refreshstatus);
}

bool networktool::iswificonnected()
{
    return !wifiname().isempty();
}

qstring networktool::wifiname()
{
    qstring output = executecommand("iwgetid", {"-r"});
    return parsewifiname(output);
}

bool networktool::ishotspotactive()
{
    // 方法1:使用nmcli检测
    qstring output = executecommand("nmcli", {"connection", "show", "--active"});
    if (output.contains("wifi") && output.contains("ap")) {
        return true;
    }
    
    // 方法2:检测hostapd进程
    output = executecommand("pgrep", {"hostapd"});
    return !output.isempty();
}

qstring networktool::hotspotname()
{
    // 尝试通过nmcli获取
    qstring output = executecommand("nmcli", {"device", "wifi", "show"});
    qstring name = parsehotspotname(output);
    if (!name.isempty()) return name;
    
    // 回退到读取hostapd配置
    qfile config("/etc/hostapd/hostapd.conf");
    if (config.open(qiodevice::readonly)) {
        while (!config.atend()) {
            qbytearray line = config.readline().trimmed();
            if (line.startswith("ssid=")) {
                return qstring::fromutf8(line.mid(5));
            }
        }
    }
    
    return "unknown";
}

void networktool::startautorefresh(int interval)
{
    m_refreshtimer.start(interval);
}

void networktool::stopautorefresh()
{
    m_refreshtimer.stop();
}

void networktool::refreshstatus()
{
    // 获取当前状态
    bool wificonnected = iswificonnected();
    qstring currentwifiname = wifiname();
    bool hotspotactive = ishotspotactive();
    qstring currenthotspotname = hotspotname();
    
    // 检查状态变化
    if (wificonnected != m_lastwifistate || currentwifiname != m_lastwifiname) {
        m_lastwifistate = wificonnected;
        m_lastwifiname = currentwifiname;
        emit wifistatuschanged(wificonnected, currentwifiname);
    }
    
    if (hotspotactive != m_lasthotspotstate || currenthotspotname != m_lasthotspotname) {
        m_lasthotspotstate = hotspotactive;
        m_lasthotspotname = currenthotspotname;
        emit hotspotstatuschanged(hotspotactive, currenthotspotname);
    }
}

qstring networktool::executecommand(const qstring &cmd, const qstringlist &args)
{
    qprocess process;
    process.start(cmd, args);
    if (!process.waitforfinished(1000)) {
        qwarning() << "command timeout:" << cmd << args;
        return "";
    }
    return qstring::fromutf8(process.readallstandardoutput()).trimmed();
}

qstring networktool::parsewifiname(const qstring &output)
{
    // iwgetid -r 直接返回ssid或空
    return output;
}

qstring networktool::parsehotspotname(const qstring &output)
{
    // 解析nmcli输出中的ssid
    qstringlist lines = output.split('\n');
    for (const qstring &line : lines) {
        if (line.trimmed().startswith("ssid:")) {
            return line.mid(5).trimmed();
        }
    }
    return "";
}

3.2 ui集成示例

qt widgets版本

// mainwindow.h
#include <qmainwindow>
#include "networktool.h"

namespace ui { class mainwindow; }

class mainwindow : public qmainwindow
{
    q_object
public:
    explicit mainwindow(qwidget *parent = nullptr);
    ~mainwindow();

private slots:
    void onwifistatuschanged(bool connected, const qstring &name);
    void onhotspotstatuschanged(bool active, const qstring &name);

private:
    ui::mainwindow *ui;
    networktool m_networktool;
};

// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

mainwindow::mainwindow(qwidget *parent) :
    qmainwindow(parent),
    ui(new ui::mainwindow)
{
    ui->setupui(this);
    
    // 连接信号
    connect(&m_networktool, &networktool::wifistatuschanged,
            this, &mainwindow::onwifistatuschanged);
    connect(&m_networktool, &networktool::hotspotstatuschanged,
            this, &mainwindow::onhotspotstatuschanged);
    
    // 启动自动刷新
    m_networktool.startautorefresh();
    
    // 初始化状态
    onwifistatuschanged(m_networktool.iswificonnected(), 
                       m_networktool.wifiname());
    onhotspotstatuschanged(m_networktool.ishotspotactive(),
                         m_networktool.hotspotname());
}

void mainwindow::onwifistatuschanged(bool connected, const qstring &name)
{
    ui->wifistatuslabel->settext(connected ? "已连接" : "未连接");
    ui->wifinamelabel->settext(connected ? name : "n/a");
    ui->wifiicon->setpixmap(qpixmap(connected ? ":/icons/wifi-on.png" 
                                             : ":/icons/wifi-off.png"));
}

void mainwindow::onhotspotstatuschanged(bool active, const qstring &name)
{
    ui->hotspotstatuslabel->settext(active ? "已开启" : "未开启");
    ui->hotspotnamelabel->settext(active ? name : "n/a");
    ui->hotspoticon->setpixmap(qpixmap(active ? ":/icons/hotspot-on.png"
                                            : ":/icons/hotspot-off.png"));
}

qml版本

// main.qml
import qtquick 2.15
import qtquick.controls 2.15
import qtquick.layouts 1.15

applicationwindow {
    id: window
    width: 400
    height: 300
    visible: true
    title: "网络状态监测"
    
    networktool {
        id: networktool
        onwifistatuschanged: {
            wifistatustext.text = connected ? "已连接" : "未连接"
            wifinametext.text = name || "n/a"
        }
        onhotspotstatuschanged: {
            hotspotstatustext.text = active ? "已开启" : "未开启"
            hotspotnametext.text = name || "n/a"
        }
        component.oncompleted: startautorefresh()
    }
    
    columnlayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15
        
        groupbox {
            title: "wifi状态"
            layout.fillwidth: true
            
            gridlayout {
                columns: 2
                width: parent.width
                
                label { text: "状态:" }
                label { id: wifistatustext }
                
                label { text: "名称:" }
                label { id: wifinametext }
            }
        }
        
        groupbox {
            title: "热点状态"
            layout.fillwidth: true
            
            gridlayout {
                columns: 2
                width: parent.width
                
                label { text: "状态:" }
                label { id: hotspotstatustext }
                
                label { text: "名称:" }
                label { id: hotspotnametext }
            }
        }
        
        button {
            text: "手动刷新"
            layout.alignment: qt.alignhcenter
            onclicked: networktool.refreshstatus()
        }
    }
}

四、注意事项:避坑指南

4.1 权限问题解决

常见权限错误

  • nmcli报错:“权限不足”
  • iwgetid无法获取信息

解决方案

polkit规则配置(推荐):

sudo nano /etc/polkit-1/rules.d/10-network-info.rules

添加内容:

polkit.addrule(function(action, subject) {
    if (action.id.indexof("org.freedesktop.networkmanager.") == 0 &&
        subject.isingroup("users")) {
        return polkit.result.yes;
    }
});

用户组配置

sudo usermod -ag netdev,network $user

sudo免密码(开发测试用):

echo "$user all=(all) nopasswd: /usr/bin/nmcli, /usr/bin/iwgetid" | sudo tee /etc/sudoers.d/network

4.2 系统兼容性处理

不同发行版适配

发行版检测命令配置文件路径
ubuntu/debiannmcli/iwgetid/etc/networkmanager/
centos/rhelnmcli/iw/etc/sysconfig/network-scripts/
arch linuxiw/wpa_cli/etc/netctl/

兼容性代码改进

qstring networktool::wifiname()
{
    // 尝试iwgetid
    qstring output = executecommand("iwgetid", {"-r"});
    if (!output.isempty()) return output;
    
    // 回退到iw命令
    output = executecommand("iw", {"dev", "wlan0", "link"});
    qregularexpression regex("ssid: (.+)");
    qregularexpressionmatch match = regex.match(output);
    if (match.hasmatch()) {
        return match.captured(1);
    }
    
    return "";
}

4.3 性能优化进阶

优化策略

  • 命令执行优化
// 异步执行命令
void networktool::executecommandasync(
    const qstring &cmd,
    const qstringlist &args,
    std::function<void(qstring)> callback)
{
    qprocess *process = new qprocess(this);
    connect(process, qoverload<int, qprocess::exitstatus>::of(&qprocess::finished),
        [=](int exitcode, qprocess::exitstatus exitstatus){
            if (exitstatus == qprocess::normalexit) {
                callback(qstring::fromutf8(process->readallstandardoutput()));
            }
            process->deletelater();
        });
    process->start(cmd, args);
}
  • 智能刷新机制
void networktool::refreshstatus()
{
    // 仅当界面可见时刷新
    if (!m_windowvisible) return;
    
    // 根据网络状态动态调整间隔
    if (m_lastwifistate) {
        m_refreshtimer.setinterval(5000); // 连接状态稳定时降低频率
    } else {
        m_refreshtimer.setinterval(1000); // 未连接时提高检测频率
    }
    // ...原有刷新逻辑...
}
  • 结果缓存
struct networkcache {
    bool wificonnected;
    qstring wifiname;
    bool hotspotactive;
    qstring hotspotname;
    qdatetime lastupdated;
};

networkcache m_cache;

void networktool::refreshcache()
{
    if (m_cache.lastupdated.secsto(qdatetime::currentdatetime()) < 2) {
        return; // 2秒内不重复更新
    }
    // ...更新缓存...
}

五、扩展

智能网络切换

void autoswitchnetwork()
{
    if (!m_networktool.iswificonnected() && 
        !m_networktool.ishotspotactive()) {
        // wifi断开且热点未开启时,自动开启热点
        qprocess::startdetached("nmcli", {
            "device", "wifi", "hotspot", 
            "ssid", "rescuehotspot",
            "password", "12345678"
        });
    }
}

网络质量监测

int getwifisignalstrength()
{
    qstring output = executecommand("iwconfig", {"wlan0"});
    qregularexpression regex("signal level=(-?\\d+) dbm");
    qregularexpressionmatch match = regex.match(output);
    if (match.hasmatch()) {
        return match.captured(1).toint();
    }
    return 0;
}

历史状态记录

void lognetworkstatus()
{
    qfile logfile("network_status.log");
    if (logfile.open(qiodevice::append)) {
        qstring log = qstring("%1|%2|%3|%4\n")
            .arg(qdatetime::currentdatetime().tostring())
            .arg(m_lastwifistate)
            .arg(m_lastwifiname)
            .arg(m_lasthotspotstate);
        logfile.write(log.toutf8());
    }
}

以上就是linux下实时获取wifi与热点状态的方法详解的详细内容,更多关于linux获取wifi与热点状态的资料请关注代码网其它相关文章!

(0)

相关文章:

  • Linux之nfs与autofs的使用方式

    Linux之nfs与autofs的使用方式

    nfs与autofs的使用nfs 服务端部署# 1. 安装必要软件yum -y install nfs-utils rpcbind# 2. 创建共享目录mkdi... [阅读全文]
  • Linux进程优先级解读

    1.概念1.1基本概念cpu资源分配的先后顺序,就是指进程的优先权(priority)。优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能…

    2025年08月06日 服务器
  • Linux之命令行参数详解

    1.基本概念在 linux(及其他类 unix 系统)中,命令行参数是执行命令或程序时,跟随在命令名称之后的额外信息。它们的作用是向程序传递具体指令、配置选项或操作对象,让程序根据…

    2025年08月06日 服务器
  • Linux配置交换空间(Swap)解决内存不足的具体教程

    前言在 centos 系统中,交换空间(swap)用于在物理内存不足时,临时将部分数据存储到硬盘上,以释放内存供其他进程使用。合理配置交换空间可以提升系统的稳定性和性能。1. 检查…

    2025年08月06日 服务器
  • Linux中的HTTPS协议原理分析

    不是有了http了吗??为什么还要有https呢??——>https也是一个应用层协议,是在http协议的基础上引入的一个加密层,他的产生是由于htt…

    2025年08月05日 服务器
  • Linux中的几种IO模型详解

    一、五种io模型1.1 高效io的初步理解io其实就是“input”和“output”尤其在网络部分,io的特性非常明显!!如果是在…

    2025年08月05日 服务器

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com