Qt应用层获取网络连接状态

背景:项目需要实时监测网线的插拔状态,方法有很多,分为两大块。

  1. 轮询:可以轮询cat /sys/class/net/eth0/carrier的值,连接时为1,断开时为0。或者轮询使用shell查看ifconfig中对应网卡的状态是否RUNNING,但是轮询的方法非常耗费资源,需要开启一个全局定时器。
  2. 使用Netlink与内核交互,获取驱动上报的状态,此程序仅在应用层,前提是内核已有netLink的驱动。

.h

#include <QThread>

class netlinkmonitor:public QThread
{
    Q_OBJECT
signals:
    void usbNetworkIsChanged(bool);
    void ethNetworkIsChanged(bool);
public:
    void run();
    static netlinkmonitor *getInstance(){
        if(!m_pinstance){
            m_pinstance = new netlinkmonitor;
        }
        return m_pinstance;
    }
private:
    explicit netlinkmonitor(QObject *parent = nullptr);
    static a7netlinkmonitor *m_pinstance ;

};

.cpp

#include "netlinkmonitor.h"
#include "configFile.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <string.h>
#include <QDebug>

#define BUFLEN 20480
#define NETWORK_TYPE_USB "usb0"
#define NETWORK_TYPE_ETH "eth0"
a7netlinkmonitor *netlinkmonitor::m_pinstance = nullptr;

a7netlinkmonitor::netlinkmonitor(QObject *parent):QThread(parent)
{
   
}

void netlinkmonitor::run()
{
    int fd, retval;
    char buf[BUFLEN] = {0};
    int len = BUFLEN;
    struct sockaddr_nl addr;
    struct nlmsghdr *nh;
    struct ifinfomsg *ifinfo;
    struct rtattr *attr;

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTNLGRP_LINK;
    bind(fd, (struct sockaddr*)&addr, sizeof(addr));
    while ((retval = read(fd, buf, BUFLEN)) > 0)
    {
        for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, retval); nh = NLMSG_NEXT(nh, retval))
        {
            if (nh->nlmsg_type == NLMSG_DONE)
                break;
//            else if (nh->nlmsg_type == NLMSG_ERROR)
//                return -1;
            else if (nh->nlmsg_type != RTM_NEWLINK)
                continue;
            ifinfo = (struct ifinfomsg *)NLMSG_DATA(nh);
            printf("%u: %s", ifinfo->ifi_index,
                   (ifinfo->ifi_flags & IFF_LOWER_UP) ? "up" : "down" );
            attr = (struct rtattr*)(((char*)nh) + NLMSG_SPACE(sizeof(*ifinfo)));
            len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
            for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
            {
                if (attr->rta_type == IFLA_IFNAME)
                {
                    printf(" %s", (char*)RTA_DATA(attr));
                    break;
                }
            }
            //printf("\n");
            SysConfig networkConfigWrite;
            if(!strcmp((char*)RTA_DATA(attr), NETWORK_TYPE_USB)){
                if((ifinfo->ifi_flags & IFF_LOWER_UP)){
                    emit m_pinstance->usbNetworkIsChanged(true);
                }else{
                    emit m_pinstance->usbNetworkIsChanged(false);
                }
                networkConfigWrite.setValue("usb/status",(ifinfo->ifi_flags & IFF_LOWER_UP));
            }
            if(!strcmp((char*)RTA_DATA(attr), NETWORK_TYPE_ETH)){
                if((ifinfo->ifi_flags & IFF_LOWER_UP)){
                    emit m_pinstance->ethNetworkIsChanged(true);
                }else{
                    emit m_pinstance->ethNetworkIsChanged(false);
                }
                networkConfigWrite.setValue("lan/status",(ifinfo->ifi_flags & IFF_LOWER_UP));
            }
        }
    }
}

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雲烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值