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:
    explicit netlinkmonitor(QObject *parent = nullptr);
    void run();
    static netlinkmonitor *getInstance(){
        if(!m_pinstance){
            m_pinstance = new netlinkmonitor;
        }
        return m_pinstance;
    }
private:
    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)
{
    m_pinstance = this;
}

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));
            }
        }
    }
}
发布了127 篇原创文章 · 获赞 137 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/baidu_33879812/article/details/104378940