Qt项目:网络1

文章目录

项目:网路


项目1:主机信息查询

使用QHostInfo类和QNetworkInterface类可以获取主机的一些网络信息,如IP地址[1](#使用QHostInfo类和QNetworkInterface类可以获取主机的一些网络信息,如IP地址1和MAC地址2。)和MAC地址[2](#使用QHostInfo类和QNetworkInterface类可以获取主机的一些网络信息,如IP地址1和MAC地址2。)

在Qt项目里使用Qt Network模块,需要在项目配置文件(.pro 文件)中增加一条配置语句:
QT += network


1.1 QHostInfo类和QNetworkInterface类

QHostInfo类常用函数

QHostInfo类可以根据主机名获取主机的IP地址,或者通过IP地址获取主机名。

  • static\] QString QHostInfo::**localHostName()**:返回本机主机名;

  • static\] QHostInfo QHostInfo::**fromName(const QString \&name)**:返回指定主机名的IP地址;

  • static\] void QHostInfo::**abortHostLookup(int id)**:使用 lookupHost() 返回的 ID 终止主机查找。

  • QString QHostInfo::hostName() const:返回通过IP地址查找到的主机名;

QNetworkInterface类常用的函数

QNetworkInterface类可以获得运行程序的主机名的所用IP地址和网络接口列表。

  • static\] QList QNetworkInterface::**allAddresses()**:返回主机上所有IP地址的列表(如果不需要知道子网掩码和广播地址);

  • QList QNetworkInterface::addressEntries() const:返回网络接口的IP地址列表,包括子网掩码和广播地址;
  • QString QNetworkInterface::hardwareAddress() const:返回接口的低级硬件地址,以太网里就是MAC地址;
  • bool QNetworkInterface::isValid() const:如果接口信息有效就返回true;
  • QNetworkInterface::InterfaceType QNetworkInterface::type() const:返回网络接口的类型;

1.2 主机信息查询项目实现

  1. 显示本机地址信息
c 复制代码
//获取本机主机名和IP地址按钮
void Widget::on_btnGetHostInfo_clicked()
{
    ui->plainTextEdit->clear();
    QString hostName = QHostInfo::localHostName();  //本机主机名
    qDebug()<<hostName;
    ui->plainTextEdit->appendPlainText("HostName:"+hostName+"\n");

    QHostInfo hostInfo = QHostInfo::fromName(hostName); //本机IP地址
    QList<QHostAddress> addrList = hostInfo.addresses();//IP地址列表
    if(addrList.isEmpty()) return;
    foreach(QHostAddress host, addrList){
        bool show = ui->checkBox_OnlyIPV4->isChecked(); //只显示ipv4
        //Returns the network layer protocol of the host address.
        show = show ? (host.protocol() == QAbstractSocket::IPv4Protocol):true;
        if(show){
            ui->plainTextEdit->appendPlainText("protool:"+protocolName(host.protocol()));//协议
            ui->plainTextEdit->appendPlainText("HostIPAdddress:"+host.toString());
            ui->plainTextEdit->appendPlainText(QString("isGolbal() = %1\n").arg(host.isGlobal()));
        }
    }
}

protocol()函数:返回主机地址的网络层协议

复制代码
QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
Returns the network layer protocol of the host address.

isGlobal()函数:如果地址是 IPv4 或 IPv6 全局地址,则返回 true,否则返回 false。全局地址是不为特殊目的(如环回或多播)或未来目的保留的地址。

复制代码
bool QHostAddress::isGlobal() const
Returns true if the address is an IPv4 or IPv6 global address, false otherwise. A global address is an address that is not reserved for special purposes (like loopback or multicast) or future purposes.

自定义函数protocolName(),通过协议类型返回协议名称字符串。

c 复制代码
//通过协议类型返回协议名称字符串
QString Widget::protocolName(QAbstractSocket::NetworkLayerProtocol protocol)
{
    switch (protocol) {
    case QAbstractSocket::IPv4Protocol:
        return "IPV4";
    case QAbstractSocket::IPv6Protocol:
        return "IPV6";
    case QAbstractSocket::AnyIPProtocol:
        return "Any Internet Protocol";
    default:
        return "Unknown NetWork Layer Protocol";
    }
}
  1. 查找主机地址信息

static\] int QHostInfo::**lookupHost(const QString \&name, QObject \*receiver, const char \*member)**: name表示主机名的字符串,可以是主机名、域名或IP地址;receive和member指定接收者和槽函数名称。 ```c //查找域名的IP地址 void Widget::on_btnLookkup_clicked() { ui->plainTextEdit->clear(); QString hostName = ui->comboBox->currentText(); //读取主机名 ui->plainTextEdit->appendPlainText("Searching for host information:"+hostName+"\n"); QHostInfo::lookupHost(hostName, this,SLOT(do_lookedUpHostInfo(QHostInfo))); } //查找主机信息的槽函数 void Widget::do_lookedUpHostInfo(const QHostInfo &host) { QList addrList = host.addresses(); //获取主机地址列表 if(addrList.isEmpty())return; foreach(QHostAddress host, addrList) { bool show = ui->checkBox_OnlyIPV4->isChecked(); //只显示ipv4 //Returns the network layer protocol of the host address. show = show ? (host.protocol() == QAbstractSocket::IPv4Protocol):true; if(show){ ui->plainTextEdit->appendPlainText("protool:"+protocolName(host.protocol()));//协议 ui->plainTextEdit->appendPlainText(host.toString()); ui->plainTextEdit->appendPlainText(QString("isGolbal() = %1\n").arg(host.isGlobal())); } } } ``` 3. QNetworkInterface类的使用 ```c //根据枚举值返回字符串 QString Widget::interfaceType(QNetworkInterface::InterfaceType type) { switch(type){ case QNetworkInterface::Unknown: return "Unkown"; case QNetworkInterface::Loopback: return "Loopback"; case QNetworkInterface::Ethernet: return "Etherent"; case QNetworkInterface::Wifi: return "Wifi"; default: return "Other type"; } } //allInterfaces() void Widget::on_btnAllInterface_2_clicked() { ui->plainTextEdit->clear(); QList list = QNetworkInterface::allInterfaces();//网络接口列表 foreach(QNetworkInterface interface,list){ if(!interface.isValid()) continue; // The name of the device // Hardware devices // Interface type // Subnet mask // broadcast address ui->plainTextEdit->appendPlainText("The name of the device:"+interface.humanReadableName()); ui->plainTextEdit->appendPlainText("Hardware devices:"+interface.hardwareAddress()); ui->plainTextEdit->appendPlainText("Interface type:"+interfaceType(interface.type())); QList entryList = interface.addressEntries();//地址列表 foreach(QNetworkAddressEntry entry, entryList){ ui->plainTextEdit->appendPlainText(" IP Address:"+entry.ip().toString()); ui->plainTextEdit->appendPlainText(" Subnet mask:"+entry.netmask().toString()); ui->plainTextEdit->appendPlainText(" broadcast address:"+entry.broadcast().toString()+"\n"); } } } //alladdress void Widget::on_btnAllAddress_clicked() { ui->plainTextEdit->clear(); QList addrelist = QNetworkInterface::allAddresses();//IP地址列表 if(addrelist.isEmpty()) return; foreach(QHostAddress host, addrelist){ bool show = ui->checkBox_OnlyIPV4->isChecked(); show = show ? (host.protocol() == QAbstractSocket::IPv4Protocol):true; if(show){ ui->plainTextEdit->appendPlainText("protocol:"+protocolName(host.protocol())); ui->plainTextEdit->appendPlainText("IP Address:"+host.toString()); ui->plainTextEdit->appendPlainText(QString("isGrobal() = %1\n").arg(host.isGlobal())); } } } ``` Loopback: 回送地址(Loopback Address)是本机回送地址(127.X.X.X),即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信。因此,无论什么程序,一旦使用回送地址发送数据,协议软件会立即将其返回,不进行任何网络传输。 127.0.0.1是回送地址,又指本地机,一般用来测试使用。 ### 项目2:基于HTTP的网络应用程序 QNetworkRequest 类通过 URL 发起网络协议请求,其也保存网络请求的信息,目前支持 HTTP、 FTP 和本地文件 URL 的下载或上传。 QNetworkAccessManager 类用于协调网络操作,在 QNetworkRequest 发起网络请求后, QNetworkAccessManager 负责发送网络请求,以及创建网络响应。 QNetworkReply 类表示网络请求的响应,由 QNetworkAccessManager 在发送网络请求后创建网 络响应。QNetworkReply 提供的信号 finished()、readyRead()、downloadProgress()可用于监测网络响 应的执行情况,从而进行相应的操作。 发起网络协议请求 发送网络请求,以及创建网络响应 监测网络响应 ![在这里插入图片描述](https://file.jishuzhan.net/article/1762400851638358018/ce7242a81b9edbcd9eaba39bff067cf3.webp) #### 2.1 项目中用到的函数详解 1. clearButtonEnabled : bool 此属性用于保存行编辑在不为空时是否显示清除按钮。 如果启用,行编辑在包含一些文本时会显示一个尾随清除按钮,否则,行编辑不会显示清除按钮(默认值)。 2. **默认路径按钮功能:** * \[static\] QString QDir::currentPath() 返回应用进程当前目录的绝对路径。当前目录是使用 QDir::setCurrent() 设置的最后一个目录,或者,如果从未调用过,则为父进程启动此应用进程的目录。 * bool QDir::mkdir(const QString \&dirName) const 创建一个名为 dirName 的子目录。 3. **下载按钮功能:** * QString QString::trimmed() const 返回一个字符串,该字符串删除了开头和结尾的空格。 * \[static\] QUrl QUrl::fromUserInput(const QString \&userInput) 从用户提供的 userInput 字符串返回有效的 URL(如果可以扣除)。如果不可能,则返回无效的 QUrl()。 * QString QUrl::errorString() const 如果修改此 QUrl 对象的最后一个操作遇到解析错误,则返回错误消息。如果未检测到错误,则此函数返回一个空字符串,isValid() 返回 true。 * QString QUrl::fileName(QUrl::ComponentFormattingOptions options = FullyDecoded) const 返回文档名,不包括目录路径。 * bool QFile::remove() 删除 fileName() 指定的文档。如果成功,则返回 true;否则返回 false。文档在删除之前已关闭。 * QNetworkReply \*QNetworkAccessManager::get(const QNetworkRequest \&request) 发布一个请求以获取目标请求的内容,并返回一个新的 QNetworkReply 对象,该对象打开以供读取,每当新数据到达时,该对象都会发出 readyRead() 信号。将下载内容以及相关的标题。 * \[signal\] void QIODevice::readyRead() 每当有新数据可用时,此信号就会发出一次从设备的当前读取信道读取。只有当有新数据可用时,它才会再次发出,例如,当新的网络数据有效负载到达您的网络套接字时,或者当新的数据块附加到您的设备时。 * \[signal\] void QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) 发出此信号以指示此网络请求的下载部分的进度(如果有)。如果没有与此请求关联的下载,则此信号将发出一次,其中 0 作为 bytesReceived 和 bytesTotal 的值。 * \[signal\] void QNetworkReply::finished() 当回复完成处理时,将发出此信号。发出此信号后,回复的数据或元数据将不再更新。 4. 读取下载数据 * qint64 QIODevice::write(const char \*data, qint64 maxSize) 将数据中最多 maxSize 字节的数据写入设备。返回实际写入的字节数,如果发生错误,则返回 -1。 * QByteArray QIODevice::readAll() 从设备读取所有剩余数据,并将其作为字节数组返回。 #### 2.2 主要源码 头文件 ```c #ifndef WIDGET_H #define WIDGET_H #include #include #include #include #include #include #include #include #include namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT private: QNetworkAccessManager networkManager; //网络管理 QNetworkReply *reply; //网络响应 QFile *downloadedFile; //下载保存的临时文件 public: explicit Widget(QWidget *parent = nullptr); ~Widget(); private slots: void do_finished(); void do_readyRead(); void do_downloadProgress(qint64 bytesRead, qint64 totalBytes); void on_btnDownload_clicked(); void on_btnDefaultPath_clicked(); void on_editURL_textChanged(const QString &arg1); private: Ui::Widget *ui; }; #endif // WIDGET_H ``` 源文件 ```c #include "widget.h" #include "ui_widget.h" #include Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //clearButtonEnabled : bool //This property holds whether the line edit displays a clear button when it is not empty. //If enabled, the line edit displays a trailing clear button when it contains some text, // otherwise the line edit does not show a clear button (the default). ui->editURL->setClearButtonEnabled(true); this->setLayout(ui->verticalLayout); } Widget::~Widget() { delete ui; } void Widget::do_finished() {//网络响应结束 QFileInfo fileInfo(downloadedFile->fileName()); //获取下载文件的文件名 downloadedFile->close(); delete downloadedFile; //删除临时文件 reply->deleteLater(); //由主事件循环删除此文件对象 if(ui->checkBoxOpen->isChecked()){ QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath())); } ui->btnDownload->setEnabled(true); } void Widget::do_readyRead() { //读取下载数据 downloadedFile->write(reply->readAll()); // qint64 QIODevice::write(const char *data, qint64 maxSize) // Writes at most maxSize bytes of data from data to the device. // Returns the number of bytes that were actually written, // or -1 if an error occurred. // QByteArray QIODevice::readAll() // Reads all remaining data from the device, and returns it as a byte array. } void Widget::do_downloadProgress(qint64 bytesRead, qint64 totalBytes) {//下载进度 ui->progressBar->setMaximum(totalBytes); //Holds the total amount of data to download in bytes. ui->progressBar->setValue(bytesRead); } //默认了路径 按钮 void Widget::on_btnDefaultPath_clicked() { // [static] QString QDir::currentPath() // Returns the absolute path of the application's current directory. // The current directory is the last directory set with QDir::setCurrent() or, // if that was never called, // the directory at which this application was started at by the parent process. QString curPath = QDir::currentPath(); //返回当前绝对路径给QString变量 QDir dir(curPath); //定义QDir变量 QString sub = "temp"; // bool QDir::mkdir(const QString &dirName) const // Creates a sub-directory called dirName. dir.mkdir(sub); //当前路径下创立名为sub的文件夹 ui->editPath->setText(curPath+"/"+sub+"/"); //设置lineedit的文字 } //下载按钮,开始下载 void Widget::on_btnDownload_clicked() { // QString QString::trimmed() const // Returns a string that has whitespace removed from the start and the end. QString urlSpec = ui->editURL->text().trimmed(); //将editURL中的文字给QString变量赋值 //urlspec判空 if(urlSpec.isEmpty()){ QMessageBox::information(this,"error","Please specify the download address"); return; } // [static] QUrl QUrl::fromUserInput(const QString &userInput) // Returns a valid URL from a user supplied userInput string if one can be deducted. // In the case that is not possible, an invalid QUrl() is returned. QUrl newUrl = QUrl::fromUserInput(urlSpec); //从urlSpaec里获取url //newurl判有效 if(!newUrl.isValid()){ // QString QUrl::errorString() const // Returns an error message if the last operation that modified this QUrl object ran into a parsing error. // If no error was detected, // this function returns an empty string and isValid() returns true. QString info = "The URL is invalid:"+urlSpec+"\n error:"+newUrl.errorString(); QMessageBox::information(this,"error",info); return; } QString tempDir = ui->editPath->text().trimmed(); //临时目录 if(tempDir.isEmpty()){ QMessageBox::information(this,"error","Please specify the download address"); return; } QString fullFileName = tempDir + newUrl.fileName(); //文件名 // QString QUrl::fileName(QUrl::ComponentFormattingOptions options = FullyDecoded) const // Returns the name of the file, excluding the directory path. if(QFile::exists(fullFileName)){ //如果文件存在 QFile::remove(fullFileName); //删除文件 // bool QFile::remove() // Removes the file specified by fileName(). Returns true if successful; otherwise returns false. // The file is closed before it is removed. } downloadedFile = new QFile(fullFileName); //创建临时文件 if(!downloadedFile->open(QIODevice::WriteOnly)){ QMessageBox::information(this,"error","Temporary file open error"); } ui->btnDownload->setEnabled(false); //发送网络请求,创建网络相应 reply = networkManager.get(QNetworkRequest(newUrl)); //网络响应从网络管理里面获取网络请求 // QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request) // Posts a request to obtain the contents of the target request and // returns a new QNetworkReply object opened for reading // which emits the readyRead() signal whenever new data arrives. // The contents as well as associated headers will be downloaded. // QObject *QObject::parent() const // Returns a pointer to the parent object. connect(reply, SIGNAL(readyRead()), this, SLOT(do_readyRead())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(do_downloadProgress(qint64,qint64))); connect(reply, SIGNAL(finished()), this, SLOT(do_finished())); // [signal] void QIODevice::readyRead() // This signal is emitted once every time new data is available for // reading from the device's current read channel. // It will only be emitted again once new data is available, // such as when a new payload of network data has arrived on your network socket, // or when a new block of data has been appended to your device. // [signal] void QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) // This signal is emitted to indicate the progress of the download part of // this network request, if there's any. If there's no download associated with this request, // this signal will be emitted once with 0 as the value of both bytesReceived and bytesTotal. // [signal] void QNetworkReply::finished() // This signal is emitted when the reply has finished processing. // After this signal is emitted, there will be no more updates to the reply's data or metadata. } void Widget::on_editURL_textChanged(const QString &arg1) { Q_UNUSED(arg1); ui->progressBar->setMaximum(100); ui->progressBar->setValue(0); } ``` *** ** * ** *** 1. IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。 [↩︎](#↩︎) 2. MAC地址(英语:Media Access Control Address),直译为媒体存取控制位址,也称为局域网地址(LAN Address),MAC位址,以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的位址。在OSI模型中,第三层网络层负责IP地址,第二层数据链路层则负责MAC位址。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。 [↩︎](#↩︎)

相关推荐
投笔丶从戎17 分钟前
Kotlin Multiplatform--01:项目结构基础
android·开发语言·kotlin
OpenC++27 分钟前
【C++QT】Buttons 按钮控件详解
c++·经验分享·qt·leetcode·microsoft
诡异森林。27 分钟前
Docker--Docker网络原理
网络·docker·容器
ALex_zry41 分钟前
Docker Macvlan网络配置实战:解决“network already exists“错误
网络·docker·php
半路_出家ren1 小时前
流量抓取工具(wireshark)
网络·网络协议·测试工具·网络安全·wireshark·流量抓取工具
杜小暑1 小时前
动态内存管理
c语言·开发语言·动态内存管理
想不明白的过度思考者1 小时前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
我真的不会C1 小时前
QT窗口相关控件及其属性
开发语言·qt
CodeCraft Studio1 小时前
Excel处理控件Aspose.Cells教程:使用 Python 在 Excel 中进行数据验
开发语言·python·excel
火柴盒zhang1 小时前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet