本帖最后由 正点原子运营 于 2022-8-10 17:33 编辑
1)实验平台:正点原子阿尔法Linux开发板
2) 章节摘自【正点原子】《I.MX6U 嵌入式Qt开发指南》
3)购买链接:https://detail.tmall.com/item.htm?id=609033604451
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/arm-linux/zdyz-i.mx6ull.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子阿尔法Linux交流群:1027879335
第十一章 网络编程
Qt网络模块为我们提供了编写TCP / IP客户端和服务器的类。它提供了较低级别的类,例如代表低级网络概念的QTcpSocket,QTcpServer和QUdpSocket,以及诸如QNetworkRequest,QNetworkReply和QNetworkAccessManager之类的高级类来执行使用通用协议的网络操作。 它还提供了诸如QNetworkConfiguration,QNetworkConfigurationManager和QNetworkSession等类,实现承载管理。 想要在程序中使用Qt网络模块,我们需要在pro项目配置文件里增加下面的一条语句。
11.1 获取本机的网络信息 为什么先写获取本机网络信息的内容呢?在建立网络通信之前我们至少得获取对方的IP地址。在网络应用中,经常需要用到本机的主机名、IP地址、MAC地址等网络信息,通常通在Windows通过调出命令行cmd窗口输入ipconfig或者在Linux系统中使用ifconfig命令就可以查看相关信息了,在这里我们利用Qt做出一个可以查询的界面和功能出来,为了后面的网络编程打下一个简单的基础。 Qt提供了QHostInfo和QNetworkInterface类可以用于此类信息查询。更多关于QHostInfo和QNetworkInterface的相关函数可以在Qt的帮助文档中找到。下面我们写代码时会使用到相关的函数,有清楚的注释。
11.1.1 应用实例 本例目的:了解如何通过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.cpp”具体代码如下。 - mainwindow.cpp编程后的代码
- /******************************************************************
- Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
- * @projectName 07_networkhostinfo
- * @brief mainwindow.cpp
- * @author Deng Zhimao
- * @email 1252699831@qq.com
- * @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类型的信息。筛选信息在我们写程序常常需要的。
11.1.2 程序运行效果 点击获取本机信息,在文本浏览框内就打印出本机的网络信息(包括了主机名,网卡名,ip地址等)。这里因为过滤掉了IPv6的信息。通常一个网卡有两个ip地址,一个是ipv4,另一个是ipv6的地址。下面的网卡设备lo,是本地回环网卡。另一个ens33是虚拟机的网卡,由VMware虚拟出来的。点击清空文本信息会清空文本浏览框里的网络信息。
|