Qt网络编程-使用QNetworkInterface获取网卡信息和IP地址Demo(7) 原创

Qt网络编程-使用QNetworkInterface获取网卡信息和IP地址Demo(7)🎧

更多精彩内容
👉个人内容分类汇总 👈

1、概述📻

Qt使用QNetworkInterface获取当前系统的网卡信息和IP地址信息,注意:Qt版本5.12.12,程序中有些功能比较新,在版本比较低在Qt中可能没有,比如:QNetworkInterface::type()在5.11以后才有

第一,绝对不意气用事;

第二,绝对不放过任何一个注释;

第三,绝对保证代码的简洁明了。🤘

在Qt实现网络通信时,常常需要获取本地IP地址或者网卡信息,例如两个TCP通信,需要知道对方IP地址,又不想每次都ipcofnig查询,想在程序中自动获取IP地址,那就需要看看本文了;

而当系统有多个网卡或者多个IP地址时,单独的知道一个IP地址是不够的,就需要获取所有的网卡信息和所有的IP地址信息。

实现功能:

  • 获取所有网络接口;
  • 获取网络接口索引;
  • 获取网络接口最大传输数据单元;
  • 获取网络接口名称;
  • 获取网络接口关联标志;
  • 获取网络接口类型说明;
  • 获取网络接口物理地址;
  • 获取IPv6地址、子网掩码
  • 获取IPv4地址、子网掩码、广播地址。

2、使用的类🎷

类名作用
QNetworkInterface用于获取网卡详细信息和IP、子网掩码、广播地址等信息
QNetworkAddressEntry包含IP、子网掩码、广播地址等信息

3、关键函数 🎸

函数名说明
allInterfaces返回主机上找到的所有网络接口(网卡)的列表
humanReadableName返回可以读懂的接口名称,如果名称不确定,得到的就是name函数的返回值
interfaceFromName根据输入网络接口名称参数,返回名为 name 的接口的 QNetworkInterface 对象
index返回网络接口的索引
maximumTransmissionUnit返回网络接口的最大传输数据单元。
name返回网络接口名称
flags返回网络接口关联标志枚举
type返回网络接口类型(如以太网、wifi、虚拟网卡)
hardwareAddress返回网络接口的物理地址(MAC地址)
addressEntries返回网络接口中所有QNetworkAddressEntry对象

4、主要代码🎹

  • 注意:.pro文件里添加QT += network,否则编译失败。
  • .h文件
/******************************************************************************
 * @文件名     netproperty.h
 * @功能       使用QNetworkInterface类获取当前系统所有的网卡信息,如IP地址,物理地址,网卡类型等
 *
 * @开发者     mhf
 * @邮箱       1603291350@qq.com
 * @时间       2022/04/22
 * @备注
 *****************************************************************************/
#ifndef NETPROPERTY_H
#define NETPROPERTY_H

#include <QWidget>

namespace Ui {
class NetProperty;
}

class NetProperty : public QWidget
{
    Q_OBJECT

public:
    explicit NetProperty(QWidget *parent = nullptr);
    ~NetProperty();

private slots:
    void on_com_Interface_activated(int index);

private:

    void init();
    QString TypeToQString(int type);

private:
    Ui::NetProperty *ui;
};

#endif // NETPROPERTY_H

  • .cpp文件
#include "netproperty.h"
#include "ui_netproperty.h"

#include <QMetaEnum>
#include <qnetworkinterface.h>
#include <QDeadlineTimer>

NetProperty::NetProperty(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::NetProperty)
{
    ui->setupUi(this);

    this->setWindowTitle("Qt使用QNetworkInterface获取网卡信息、IP地址Demo");
    // 表格自适应
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);                 // 设置如何将标题大小调整为给定模式所述大小的约束。
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);     // 然后设置要根据内容使用宽度的列

    init();
}

NetProperty::~NetProperty()
{
    delete ui;
}

/**
 * @brief 获取所有的网卡可读名称
 */
void NetProperty::init()
{
    // 获取所有网络接口
    const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();

    ui->com_Interface->clear();
    for(const QNetworkInterface& interface : interfaces)
    {
        ui->com_Interface->addItem(interface.humanReadableName(), interface.name());       // 显示所有网络接口名称
    }
}

/**
 * @brief        通过下列框选择网卡名,显示选择网卡的所有信息
 * @param index
 */
void NetProperty::on_com_Interface_activated(int index)
{
    Q_UNUSED(index)
    QString strName = ui->com_Interface->currentData().toString();
    QNetworkInterface interface =  QNetworkInterface::interfaceFromName(strName);   // 根据选择名称获取网卡

    if(!interface.isValid())   // 判断接口有效
    {
        return;
    }
    ui->tableWidget->item(0, 1)->setText(QString::number(interface.index()));                     // 获取网卡索引
    ui->tableWidget->item(1, 1)->setText(QString::number(interface.maximumTransmissionUnit()));   // 获取网卡最大传输数据单元
    ui->tableWidget->item(2, 1)->setText(interface.name());                                       // 获取网卡名称

#if 0    // 直接显示标志枚举
    QNetworkInterface::InterfaceFlags flags = interface.flags();
    QMetaEnum metaEnum = QMetaEnum::fromType<QNetworkInterface::InterfaceFlags>();
    ui->tableWidget->item(3, 1)->setText(metaEnum.valueToKeys(flags));                            // 返回与此网络接口关联的标志
#else
    ui->tableWidget->item(3, 1)->setText(FlagsToQString(interface.flags()));
#endif
    ui->tableWidget->item(4, 1)->setText(TypeToQString(interface.type()));                        // 获取网络类型说明
    ui->tableWidget->item(5, 1)->setText(interface.hardwareAddress());                            // // 获取MAC地址

    ui->textEdit_ip->clear();
    // 如果只是获取所有的IP地址可以使用allAddresses()函数
    const QList<QNetworkAddressEntry> entrys = interface.addressEntries();  // 返回此接口拥有的 IP 地址列表及其关联的网络掩码和广播地址。
    for(auto entery : entrys)
    {
        QString strType;
        switch (entery.ip().protocol())       // 判断IP地址类型
        {
        case QAbstractSocket::IPv4Protocol:
            strType = "--------IPv4地址--------";
            break;
        case QAbstractSocket::IPv6Protocol:
            strType = "--------IPv6地址--------";
            break;
        case QAbstractSocket::AnyIPProtocol:
            strType = "--------IPv4或IPv6地址--------";
            break;
        case QAbstractSocket::UnknownNetworkLayerProtocol:
            strType = "--------未知地址--------";
            break;
        }
        ui->textEdit_ip->append(strType);             // 显示IP地址类型
        QString ipInfo = QString("IP地址:%1,子网掩码:%2,广播地址:%3").arg(entery.ip().toString())
                .arg(entery.netmask().toString())
                .arg(entery.broadcast().toString());
        ui->textEdit_ip->append(ipInfo);              // 显示IP地址信息
    }
}

/**
 * @brief        将网卡关联标志转换为可读的说明信息
 * @param flags
 * @return
 */
QString NetProperty::FlagsToQString(int flags)
{
    QString strFlags;
    if(flags & QNetworkInterface::IsUp)
    {
        strFlags += "网络接口处于活动状态";
    }
    if(flags & QNetworkInterface::IsRunning)
    {
        strFlags.append(strFlags.isEmpty() ? "" : " | ");
        strFlags += "网络接口已分配资源";
    }
    if(flags & QNetworkInterface::CanBroadcast)
    {
        strFlags.append(strFlags.isEmpty() ? "" : " | ");
        strFlags += "网络接口工作在广播模式";
    }
    if(flags & QNetworkInterface::IsLoopBack)
    {
        strFlags.append(strFlags.isEmpty() ? "" : " | ");
        strFlags += "网络接口是一个环回接口";
    }
    if(flags & QNetworkInterface::IsPointToPoint)
    {
        strFlags.append(strFlags.isEmpty() ? "" : " | ");
        strFlags += "网络接口是一个点对点接口";
    }
    if(flags & QNetworkInterface::CanMulticast)
    {
        strFlags.append(strFlags.isEmpty() ? "" : " | ");
        strFlags += "网络接口支持组播";
    }
    return strFlags;
}


/**
 * @brief        返回网卡类型说明
 * @param type   网卡类型枚举
 * @return       网卡类型说明
 */
QString NetProperty::TypeToQString(int type)
{
    switch (type)
    {
    case QNetworkInterface::Loopback: return "虚拟环回接口,分配了环回 IP 地址 (127.0.0.1, ::1)";
    case QNetworkInterface::Virtual:  return "一种确定为虚拟的接口类型,但不是任何其他可能的类型";
    case QNetworkInterface::Ethernet: return "IEEE 802.3 以太网接口";
    case QNetworkInterface::Slip:     return "串行线路互联网协议接口";
    case QNetworkInterface::CanBus:   return "ISO 11898 控制器局域网总线接口";
    case QNetworkInterface::Ppp:      return "点对点协议接口,通过较低的传输层(通常通过无线电或物理线路串行)在两个节点之间建立直接连接";
    case QNetworkInterface::Fddi:     return "ANSI X3T12 光纤分布式数据接口,一种光纤局域网";
    case QNetworkInterface::Wifi:     return "IEEE 802.11 Wi-Fi 接口";         // 别名 Ieee80211
    case QNetworkInterface::Phonet:   return "使用 Linux Phonet socket系列的接口,用于与蜂窝调制解调器通信";
    case QNetworkInterface::Ieee802154: return "IEEE 802.15.4 个人区域网络接口,6LoWPAN 除外";
    case QNetworkInterface::SixLoWPAN:  return "6LoWPAN(低功耗无线个人区域网络上的 IPv6)接口,通常用于网状网络";
    case QNetworkInterface::Ieee80216:  return "IEEE 802.16 无线城域网";
    case QNetworkInterface::Ieee1394:   return "IEEE 1394 接口(又名“FireWire”)";
    case QNetworkInterface::Unknown:    return "接口类型无法确定或不是其他列出的类型之一";
    default:return "未知";
    }
}

5、实现效果🎺

在这里插入图片描述

6、源代码🥁

gitee
github

📞📞📞📞📞📞📞📞📞📞📞📞

posted @ 2022-04-23 23:18  mahuifa  阅读(0)  评论(0编辑  收藏  举报  来源