简 述: 了解主机信息查询QHostInfoQNetworkInterface查询IP等函数接口的使用,书写一个简单地例子;然后写了一个小的 Qt例子,用来实现和验证它的空间的一些属性和功能的用法。

[TOC]


本文初发于 “偕臧的小站” ifmet.cn,同步转载于此。


系统环境:

编程环境: MacOS 10.14.6 (18G103) 编程软件: Qt 5.9.8Qt Creator 4.8.2


网络相关知识:

终于讲解到了我之前就心心恋恋的网络模块的知识了,有几个点一直是很想涉及的知识模块👏👏👏;一个是网络,另外一个就是多线程的相关知识;柑橘🍊现在很多电脑💻的应用程序都会使用到这两个部分的知识模块,再➕一个数据库📚就是==App? 成为一个独立的开发者,可以写一个自己喜欢的exe或者app,慢慢打磨;人生易短,做自己喜欢的事情,💰不¥$$💰的都是无所谓的。谁都有离开的一天,die是不可避免的,可我们如何证明自己来这这里玩过几十载呢?总的留下一些什么的痕迹吧~

或许朝闻道,夕死可矣~ ???

来自一个12-25🎄🎄🎄🎄:夜间没人约会的+上班的孤独狗 ➜ 🐶👨 的一篇博客📝

有点跑偏了:

网络模块的相关知识,主要就是七层协议原理 和它们衍生出来的网络协议,有N多种,其中经过时间的检验和筛选,现在常用的就是TCP/IP协议族,展开就是TCP,UDP,HTTP,HTTPS,ftp,socket等等

网络相关:

建议开始之前,先问问自己如下问题,自己能够区分概念是什么,自己懂了吗❓❓❓

  • mac地址
  • IP地址
  • port端口
  • 主机名
  • 子网掩码,A/B/C/D四类地址
  • 数据包? 报文?自定义协议?
  • 通信协议有哪些?
  • 三次握手🤝,四次挥手👋?
  • TCP/UDP/Http区别
  • 数据包经过路由器如何转到下一台设备?
  • 一款程序是怎么在局域网之间通信的?
  • 一款程序是怎么在互联网之间通信的?

关于网络更底层的协议和实现的原理的相关学习知识,可以多看看👀下面这两个视频链接,我就是之前学习的此mooc网络课,觉得讲解的很棒,故此口口相传的推荐出来:


QHostInfo属性:

得益于Qt强大的封装库,上面的很多细节都不用深究,只需要创建一两个对象,然后调用他们的函数,就可以获得他们的网络相关的信息;

QHostInfo类可以通过静态函数localHostName()获取 本机的主机名 再通过fromName()函数可以获取到 IP地址,而lookupHost()则是通过异步方式查询到这个主机的IP地址。

类别 函数原型 作用
公共函数 QList addresses() 返回与hostName()关联的IP地址列表
公共函数 HostInfoError error() 如果主机查找失败,返回失败类型
公共函数 QString errorString() 如果主机查找失败,返回错误描述字符串
公共函数 QString hostName() 返回通过IP查找的主机名称
公共函数 int lookupld() 返回本次查找的id
静态函数 void abortHostLookup(int id) 中断主机查找
静态函数 QHostInfo fromName(QString &name) 返回指定主机名IP的地址
静态函数 QString localDomainName() 返回本机DNS域名
静态函数 QString localHostName() 返回本机主机名
静态函数 int lookupHost(QString byname, QObject *receiver, char *member) 以异步方式根据主机名查找主机的IP地址,并返回一个表示本次查找的ID,可用于abortHostLookup()
//QHostInfo 获取主机信息
    QString hostName = QHostInfo::localHostName();
    ui->plainTextEdit->appendPlainText("本地主机名称:" + hostName + "\n");

    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QList<QHostAddress> list = hostInfo.addresses();

    if (list.isEmpty())
        return;

    foreach (QHostAddress var, list) {
        bool bIPv4 = ui->checkBox->isChecked();

        if (bIPv4) {   //只显示 IPv4
            bIPv4 = QAbstractSocket::IPv4Protocol == var.protocol();
        } else {
            bIPv4 = true;   //显示 IPv4 和 IPv6
        }

        if (bIPv4) {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(var.protocol()));
            ui->plainTextEdit->appendPlainText("本机IP地址" + var.toString() + "\n");
        }
    }

QNetworkInterface属性:

QNetworkInterface类是可以获得应用程序的主机的所有IP地址和网络地址接口的列表。静态函数allInterfaces()返回主机上所有网络接口的列表,一个网络接口可能包含多个IP地址,每个IP地址与地址掩码或广播地址的关联;当然也有一个简版的获取函数allAddresses()可以获取到,但是不会返回子网掩码和广播的IP地址。

类别 函数原型 作用
公共函数 QList addressEntries() 返回该网络接口(包含子网掩码+广播地址)的IP地址列表
公共函数 QString hardwareAddress() 返回该接口的低级硬件地址,以太网里就是MAC地址
公共函数 QString humanReadableName() 返回可以读懂的接口名称没如果名称不确定,得到的就是name()的返回值
公共函数 bool isValid() 如果接口信息有效就返回true
公共函数 QString name() 返回主机上所有IP地址的列表
静态函数 QList allAddresses() 返回主机上面的所有IP地址的列表
静态函数 QList allInterfaces() 返回主机上面的所有接口的网络列表

QAbstractSocket属性:

QAbstractSocket::NetworkLayerProtocol 枚举:

该枚举描述了Qt中使用的网络层协议值。

Constant Value Description
QAbstractSocket::IPv4Protocol 0 IPv4
QAbstractSocket::IPv6Protocol 1 IPv6
QAbstractSocket::AnyIPProtocol 2 Either IPv4 or IPv6
QAbstractSocket::UnknownNetworkLayerProtocol -1 Other than IPv4 and IPv6

运行效果:

这里上一张运行效果图:


源码分析:

其中核心部分的源码,重点和一些难点以及需要注意的一些地方,贴出来如下

其中.h头文件如下:

#ifndef EXQHOSTINFO_H
#define EXQHOSTINFO_H

#include <QWidget>
#include <QAbstractSocket>
class QHostInfo;


namespace Ui {
class ExQHostInfo;
}

class ExQHostInfo : public QWidget
{
    Q_OBJECT

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

private:
    QString protocolName(QAbstractSocket::NetworkLayerProtocol protocol);  //通过协议类型返回协议名称

private slots:
    void on_btnGetHostInfo_clicked();    //QHostInfo查询主机名和IP
    void on_btnAllAddresses_clicked();   //QNetworkInterface::allAddresses()
    void on_btnAllInterfaces_clicked();  //QNetworkInterface::allInterfaces()
    void on_btnFindIP_clicked();         //QHostInfo查询左侧域名IP地址
    void on_btnClean_clicked();          //清空文本框信息

    void onLookedUpHostInfo(const QHostInfo& host);  //查询主机信息的槽函数

private:
    Ui::ExQHostInfo *ui;

};

#endif // EXQHOSTINFO_H

其中.cpp源文件如下:

#include "ExQHostInfo.h"
#include "ui_ExQHostInfo.h"

#include <QHostInfo>
#include <QNetworkInterface>

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

    setWindowTitle("QHostInfo/QNetworkInterface查询主机网络状态:");
}

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

//通过协议类型返回协议名称
QString ExQHostInfo::protocolName(QAbstractSocket::NetworkLayerProtocol protocol)
{
    switch (protocol) {
    case QAbstractSocket::IPv4Protocol:
        return "IPv4 Protocol";
    case QAbstractSocket::IPv6Protocol:
        return "IPv6 Protocol";
    case QAbstractSocket::AnyIPProtocol:
        return "Any IP Protocol";
    default:
        return "Unknow Network Layer Protocol";
    }
}

//QHostInfo 获取主机信息
void ExQHostInfo::on_btnGetHostInfo_clicked()
{
    QString hostName = QHostInfo::localHostName();
    ui->plainTextEdit->appendPlainText("本地主机名称:" + hostName + "\n");

    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QList<QHostAddress> list = hostInfo.addresses();

    if (list.isEmpty())
        return;

    foreach (QHostAddress var, list) {
        bool bIPv4 = ui->checkBox->isChecked();

        if (bIPv4) {   //只显示 IPv4
            bIPv4 = QAbstractSocket::IPv4Protocol == var.protocol();
        } else {
            bIPv4 = true;   //显示 IPv4 和 IPv6
        }

        if (bIPv4) {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(var.protocol()));
            ui->plainTextEdit->appendPlainText("本机IP地址" + var.toString() + "\n");
        }
    }
}

void ExQHostInfo::on_btnAllAddresses_clicked()
{
    QList<QHostAddress> list = QNetworkInterface::allAddresses();

    if (list.isEmpty())
        return;

    foreach (QHostAddress var, list) {
        bool bIPv4 = ui->checkBox->isChecked();

        if (bIPv4) {   //只显示 IPv4
            bIPv4 = QAbstractSocket::IPv4Protocol == var.protocol();
        } else {
            bIPv4 = true;   //显示 IPv4 和 IPv6
        }

        if (bIPv4) {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(var.protocol()));
            ui->plainTextEdit->appendPlainText("本机IP地址" + var.toString() + "\n");
        }
    }
}

void ExQHostInfo::on_btnAllInterfaces_clicked()
{
    QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();

    if (list.isEmpty())
        return;

    foreach (QNetworkInterface var, list) {
        if (!var.isValid())
            continue;

        ui->plainTextEdit->appendPlainText("设备名称:" + var.humanReadableName());
        ui->plainTextEdit->appendPlainText("硬件地址:" + var.hardwareAddress());

        QList<QNetworkAddressEntry> entry = var.addressEntries();
        foreach (QNetworkAddressEntry ent, entry) {
            ui->plainTextEdit->appendPlainText("  IP 地址:" + ent.ip().toString());
            ui->plainTextEdit->appendPlainText("  子网掩码:" + ent.netmask().toString());
            ui->plainTextEdit->appendPlainText("  子网广播:" + ent.broadcast().toString() + "\n");
        }
    }
}

void ExQHostInfo::on_btnFindIP_clicked()
{
    QString hostName = ui->lineEdit->text();  //域名
    ui->plainTextEdit->appendPlainText("正在查找域名的服务器的主机信息:" + hostName);
    QHostInfo::lookupHost(hostName, this, SLOT(onLookedUpHostInfo(QHostInfo)));
}

void ExQHostInfo::on_btnClean_clicked()
{
    ui->plainTextEdit->clear();
}

//查询主机信息的槽函数
void ExQHostInfo::onLookedUpHostInfo(const QHostInfo &host)
{
    QList<QHostAddress> list = host.addresses();

    if (list.isEmpty())
        return;

    for (int i = 0; i < list.count(); i++) {
        QHostAddress host = list.at(i);
        bool bIpv4 = ui->checkBox->isChecked();  //只显示IPv4

        if (bIpv4) {   //只显示 IPv4
            bIpv4 = QAbstractSocket::IPv4Protocol == host.protocol();
        } else {
            bIpv4 = true;   //显示 IPv4 和 IPv6
        }

        if (bIpv4) {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(host.protocol()));
            ui->plainTextEdit->appendPlainText(host.toString());
        }
    }
}

源码下载:

https://github.com/xmuli/QtExamples 【QtQHostInfoEx】