Qt 网络模块为我们提供了编写 TCP / IP 客户端和服务器的类。它提供了较低级别的类,例
如代表低级网络概念的 QTcpSocket,QTcpServer 和 QUdpSocket,以及诸如 QNetworkRequest,
QNetworkReply 和 QNetworkAccessManager 之类的高级类来执行使用通用协议的网络操作。 它
还提供了诸如QNetworkConfiguration,QNetworkConfigurationManager和QNetworkSession等类,
实现承载管理。
想要在程序中使用 Qt 网络模块,我们需要在 pro 项目配置文件里增加下面的一条语句。
QT += network \
为什么先写获取本机网络信息的内容呢?在建立网络通信之前我们至少得获取对方的 IP
地址。在网络应用中,经常需要用到本机的主机名、IP 地址、MAC 地址等网络信息,通常通
在 Windows 通过调出命令行 cmd 窗口输入 ipconfig 或者在 Linux 系统中使用 ifconfig 命令就可
以查看相关信息了,在这里我们利用 Qt 做出一个可以查询的界面和功能出来,为了后面的网络
编程打下一个简单的基础。
Qt 提供了 QHostInfo 和 QNetworkInterface 类可以用于此类信息查询。更多关于 QHostInfo
和 QNetworkInterface 的相关函数可以在 Qt 的帮助文档中找到。下面我们写代码时会使用到相
关的函数,有清楚的注释。
本例目的:了解如何通过 QHostInfo 和 QNetworkInterface 类获取本地网络所有接口的信息。
例 07_networkhostinfo , 获 取 本 机 网 络 接 口 信 息 ( 难 度 : 一 般 )。 项 目 路 径 为
Qt/2/07_networkhostinfo。本例获取本机的网络接口信息,打印在文本浏览框上,点击按钮可直
接获取,为了清楚看见是重新获取的过程,本例点击获取本机信息按钮后延时 1s 去刷新获取的
信息。点击另一个清空文本信息按钮可以清空文本浏览框上的文本内容。
项目文件 07_networkhostinfo.pro 文件第一行添加的代码部分如下。
07_ networkhostinfo.pro 编程后的代码
1 QT += core gui network
2
3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
4
5 CONFIG += c++11
6
7 # The following define makes your compiler emit warnings if you use
8 # any Qt feature that has been marked deprecated (the exact warnings
9 # depend on your compiler). Please consult the documentation of the
10 # deprecated API in order to know how to port your code away from it.
11 DEFINES += QT_DEPRECATED_WARNINGS
12
13 # You can also make your code fail to compile if it uses deprecated APIs.
14 # In order to do so, uncomment the following line.
15 # You can also select to disable deprecated APIs only up to a certain
version of Qt.
16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the
APIs deprecated before Qt 6.0.0
17
18 SOURCES += \
19 main.cpp \
20 mainwindow.cpp
21
22 HEADERS += \
23 mainwindow.h
24
25 # Default rules for deployment.
26 qnx: target.path = /tmp/$${TARGET}/bin
27 else: unix:!android: target.path = /opt/$${TARGET}/bin
28 !isEmpty(target.path): INSTALLS += target
在头文件“mainwindow.h”具体代码如下。
mainwindow.h 编程后的代码
/******************************************************************
Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
* @projectName 07_networkhostinfo
* @brief mainwindow.h
* @author Deng Zhimao
* @email [email protected]
* @net www.openedv.com
* @date 2021-04-10
*******************************************************************/
1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include <QMainWindow>
5 #include <QPushButton>
6 #include <QTextBrowser>
7 #include <QVBoxLayout>
8 #include <QHBoxLayout>
9 #include <QTimer>
10
11 class MainWindow : public QMainWindow
12 {
13 Q_OBJECT
14
15 public:
16 MainWindow(QWidget *parent = nullptr);
17 ~MainWindow();
18
19 private:
20 /* 点击获取和清空文本按钮 */
21 QPushButton *pushButton[2];
22
23 /* 文本浏览框用于显示本机的信息 */
24 QTextBrowser *textBrowser;
25
26 /* 水平 Widget 容器和垂直 Widget 容器*/
27 QWidget *hWidget;
28 QWidget *vWidget;
30 /* 水平布局和垂直布局 */
31 QHBoxLayout *hBoxLayout;
32 QVBoxLayout *vBoxLayout;
33
34 /* 定时器 */
35 QTimer *timer;
36
37 /* 获取本机的网络的信息,返回类型是 QString */
38 QString getHostInfo();
39
40 private slots:
41 /* 定时器槽函数,点击按钮后定时触发 */
42 void timerTimeOut();
43
44 /* 显示本机信息 */
45 void showHostInfo();
46
47 /* 启动定时器 */
48 void timerStart();
49
50 /* 清空 textBrowser 的信息 */
51 void clearHostInfo();
52 };
53 #endif // MAINWINDOW_H
54
头文件里主要是声明两个按钮和一个文本浏览框。另外还有一个定时器,声明一些槽函数,
比较简单。
在源文件“mainwindow.cpp”具体代码如下。
mainwindow.cpp 编程后的代码
/******************************************************************
Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
* @projectName 07_networkhostinfo
* @brief mainwindow.cpp
* @author Deng Zhimao
* @email [email protected]
* @net www.openedv.com
* @date 2021-04-10
*******************************************************************/
1 #include "mainwindow.h"
2 #include <QNetworkInterface>
3 #include <QHostInfo>
4 #include <QThread>
5 #include <QDebug>
6
7 MainWindow::MainWindow(QWidget *parent)
8 : QMainWindow(parent)
9 {
10 /* 设置位置与大小 */
11 this->setGeometry(0, 0, 800, 480);
12
13 /* 点击获取本地信息按钮和清空文本按钮 */
14 pushButton[0] = new QPushButton();
15 pushButton[1] = new QPushButton();
16
17 pushButton[0]->setText("获取本机信息");
18 pushButton[1]->setText("清空文本信息");
19
20 /* 按钮的大小根据文本自适应,
21 * 注意 setSizePolicy 需要在布局中使用 */
22 pushButton[0]->setSizePolicy(QSizePolicy::Fixed,
23 QSizePolicy::Fixed);
24 pushButton[1]->setSizePolicy(QSizePolicy::Fixed,
25 QSizePolicy::Fixed);
26
27 /* 水平 Widget 和垂直 Widget 用于添加布局 */
28 hWidget = new QWidget();
29 vWidget = new QWidget();
30
31 /* 水平布局和垂直布局 */
32 hBoxLayout = new QHBoxLayout();
33 vBoxLayout = new QVBoxLayout();
34
35 /* 文本浏览框 */
36 textBrowser = new QTextBrowser();
37
38 /* 添加到水平布局 */
39 hBoxLayout->addWidget(pushButton[0]);
40 hBoxLayout->addWidget(pushButton[1]);
41
42 /* 将水平布局设置为 hWidget 的布局 */
43 hWidget->setLayout(hBoxLayout);
44
45 /* 将文本浏览框和 hWidget 添加到垂直布局 */
46 vBoxLayout->addWidget(textBrowser);
47 vBoxLayout->addWidget(hWidget);
48
49 /* 将垂直布局设置为 vWidget 的布局 */
50 vWidget->setLayout(vBoxLayout);
51
52 /* 设置 vWidget 为中心部件 */
53 setCentralWidget(vWidget);
54
55 /* 定时器初始化 */
56 timer = new QTimer();
57
58 /* 信号槽连接 */
59 connect(pushButton[0], SIGNAL(clicked()),
60 this, SLOT(timerStart()));
61 connect(pushButton[1], SIGNAL(clicked()),
62 this, SLOT(clearHostInfo()));
63 connect(timer, SIGNAL(timeout()),
64 this, SLOT(timerTimeOut()));
65 }
66
67 MainWindow::~MainWindow()
68 {
69 }
70
71
72 void MainWindow::timerStart()
73 {
74 /* 清空文本 */
75 textBrowser->clear();
76
77 /* 定时 1s */
78 timer->start(1000);
79 }
80
81 void MainWindow::timerTimeOut()
82 {
83 /* 显示本机信息 */
84 showHostInfo();
85
86 /* 停止定时器 */
87 timer->stop();
88 }
89
90 QString MainWindow::getHostInfo()
91 {
92 /* 通过 QHostInfo 的 localHostName 函数获取主机名称 */
93 QString str = "主机名称:" + QHostInfo::localHostName() + "\n";
94
95 /* 获取所有的网络接口,
96 * QNetworkInterface 类提供主机的 IP 地址和网络接口的列表 */
97 QList<QNetworkInterface> list
98 = QNetworkInterface::allInterfaces();
99
100 /* 遍历 list */
101 foreach (QNetworkInterface interface, list) {
102 str+= "网卡设备:" + interface.name() + "\n";
103 str+= "MAC 地址:" + interface.hardwareAddress() + "\n";
104
105 /* QNetworkAddressEntry 类存储 IP 地址子网掩码和广播地址 */
106 QList<QNetworkAddressEntry> entryList
107 = interface.addressEntries();
108
109 /* 遍历 entryList */
110 foreach (QNetworkAddressEntry entry, entryList) {
111 /* 过滤 IPv6 地址,只留下 IPv4 */
112 if (entry.ip().protocol() ==
113 QAbstractSocket::IPv4Protocol) {
114 str+= "IP 地址:" + entry.ip().toString() + "\n";
115 str+= "子网掩码:" + entry.netmask().toString() + "\n";
116 str+= "广播地址:" + entry.broadcast().toString() + "\n\n";
117 }
118 }
119 }
120
121 /* 返回网络信息 */
122 return str;
123 }
124
125 void MainWindow::showHostInfo()
126 {
127 /* 获取本机信息后显示到 textBrowser */
128 textBrowser->insertPlainText(getHostInfo());
129 }
130
131 void MainWindow::clearHostInfo()
132 {
133 /* 判断 textBrowser 是否为空,如果不为空则清空文本 */
134 if (!textBrowser->toPlainText().isEmpty())
135
136 /* 清空文本 */
137 textBrowser->clear();
138 }
第 90~123 行,是本例最重要的代码。
第 93 行,通过 QHostInfo 的 localHostName 函数获取主机名称。
第 97~98 行,通过 QNetworkInterface::allInterfaces()获取网络接口列表 list 类存储 IP 地址子
网掩码和广播地址。如果我们用 qDebug()函数打印出 list,可以发现获取了所有的网络信息。
而我们要提取网络里面的网络信息使用 QNetworkAddressEntry。
第 106~107 行,使用 QNetworkAddressEntry 从 interface 接口里使用函数 addressEntries(),
获取所有的条目。就可以使用 QNetworkAddressEntry 的对象 entry 获取 IP 地址子网掩码和广播
地址。
第 110~118 行,因为获取的 entries 在一个 QNetworkInterface 下可能有两个 IP,分别是 ipv4
和 ipv6。这里使用 ip().protocol()来判断协议的类型,只留下 ipv4 类型的信息。筛选信息在我们
写程序常常需要的。
点击获取本机信息,在文本浏览框内就打印出本机的网络信息(包括了主机名,网卡名,
ip 地址等)。这里因为过滤掉了 IPv6 的信息。通常一个网卡有两个 ip 地址,一个是 ipv4,另一
个是 ipv6 的地址。下面的网卡设备 lo,是本地回环网卡。另一个 ens33 是虚拟机的网卡,由
VMware 虚拟出来的。点击清空文本信息会清空文本浏览框里的网络信息。