基于VS2022+Qt5+C++的网络调试助手开发

2024-09-07 22:44

本文主要是介绍基于VS2022+Qt5+C++的网络调试助手开发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、前言

二、环境准备以及项目创建

三、 项目实现

1.ui界面设计

2.添加NetWork模块 

 QTcpSocket 和 QTcpServer

QUdpSocket

3.主要功能实现 

①IP扫描

②端口设置 

③数据接收

④数据发送

⑤日志保存

4.打包成exe

四、效果展示

五、总结


一、前言

我之前用基于pyqt5一共实现过俩款小工具,分别是串口助手以及网络调试助手。文章如下:

基于Python+Pycharm+PyQt5的串口助手开发_基于python+pyqt5的串口助手-CSDN博客

基于PyQt5的网络调试助手开发_pyqt5做网络调试助手-CSDN博客

但是前不久呢,开始接触了QT和C++之后。我就把串口助手基于C++重写实现了一版.基于VS2022+Qt5+C++的串口助手开发_vs2022 c++串口在哪儿-CSDN博客文章浏览阅读1.5k次,点赞20次,收藏18次。如果有人之前看过我文章的话应该知道,我之前用python+pyqt5写过一版串口助手。没看过的也不要紧,我贴在下面,大家可以浅浅看一下。最近由于工作需要,开始接触C++以及QT,就想着能不能用C++和QT重写一下串口助手。于是就有了这篇文章单纯记录一下,接下来听我娓娓道来~基于Python+Pycharm+PyQt5的串口助手开发_基于python+pyqt5的串口助手-CSDN博客本期带来的基于PyQt5的串口助手开发,实现串口通信。_基于python+pyqt5的串口助手。_vs2022 c++串口在哪儿https://blog.csdn.net/weixin_44765053/article/details/141184173?spm=1001.2014.3001.5502 同样地,今天带来的文章是网络调试助手开发,基于QT和C++重写实现。

二、环境准备以及项目创建

操作系统:win 10

编辑器:VS2022、QT5.14

语言及版本:C++

最终实现的功能:UDP通信、TCP客户端/服务端通信、发送数据、接收数据、数据显示

具体的VS配置QT以及项目创建过程我这边就不再赘述,有不知道的小伙伴可以串口那边文章。

三、 项目实现

1.ui界面设计

继续偷个小懒,直接沿用pyqt网络调试助手项目的ui设计。

大致包括:

2个textEdit,分别是发送框和接受框;

2个comboBox和一个lineEdit,表示协议类型、IP以及端口;

5个checkBox,表示发送、接收格式等;

若干个pushButton;

......

ps:这边我较pyqt项目新增了一个保存日志开关,不知道是否有眼尖的小伙伴发现呢

2.添加NetWork模块 

Qt的网络模块(QtNetwork)提供了一套用于开发网络应用程序的工具,它支持多种网络协议,使得开发者可以轻松地创建客户端或服务器端的应用程序。这里我们主要用到的是QTcpSocket QTcpServer以及QUdpSocket

 QTcpSocketQTcpServer

  • QTcpSocket:封装了 TCP 客户端的功能,用于与服务器建立 TCP 连接。它提供了异步的读写接口,支持流式数据传输。
  • QTcpServer:用于创建 TCP 服务器,监听特定的端口并接受来自客户端的连接。每个新连接都会产生一个 QTcpSocket 对象,用于与客户端通信。

QUdpSocket

  • 功能:提供 UDP 通信功能,适合无连接的网络传输场景。支持广播和组播,适合实时通信或局域网内的应用。
  • 特点
    • 无连接:不需要建立连接,数据直接发送到指定 IP 和端口。
    • 快速:适合对延时敏感的应用,但不保证数据的可靠传输。

那么要怎么样才能在我们的项目中使用NetWork模块呢?

依次点击,项目-->NetAssistant和属性-->Qt Project Settings-->Qt Modules-->添加network

 

但是,往往这样只是这样还不够,会报错显示无法打开源文件QtNetWork,这时候就需要在项目--->属性---->配置属性---->C/C++---->常规---->附加包含目录”添加:

$(QTDIR)\include\QtNetwork

 

3.主要功能实现 

主要功能包括:

  • IP扫描:定时每秒扫描网卡IPV4,并将其添加到ComboBox。
  • 端口设置:根据通信协议设置绑定IP、端口。
  • 数据接收:接收数据,并以十六进制或者正常显示。
  • 数据发送:包括十六进制发送、定时发送数据等待。
  • 数据保存:将数据日志保存到log文件

①IP扫描

QNetworkInterface ,主要用于获取本地设备的网络接口信息。通过它,可以枚举系统中所有的网络接口,获取接口的名称、类型、IP 地址等相关信息。

QStringList NetAssistant::GetIp()
{// 获取系统中所有网络接口的IP地址列表QList <QHostAddress> ip_list = QNetworkInterface::allAddresses();QStringList scan_ip;  // 初始化一个空的 QStringList,用于存储扫描到的有效IP地址for (const QHostAddress& ip : ip_list) {if (ip.isNull())  // 忽略空的IP地址continue;// 获取IP地址的协议类型QAbstractSocket::NetworkLayerProtocol n_protocol = ip.protocol();// 如果协议类型为IPv4,则将IP地址添加到有效IP地址列表中if (n_protocol == QAbstractSocket::IPv4Protocol) {scan_ip.append(ip.toString());}}return scan_ip;  // 返回有效IP地址列表
}

②端口设置 

 对于UDP。QUdpSocket::bindQUdpSocket 类中的一个重要方法,用于将 UDP 套接字(socket)绑定到指定的地址和端口,从而让套接字开始监听并接收来自该端口的数据。

#include <QUdpSocket>
#include <QHostAddress>
#include <QDebug>int main() {QUdpSocket udpSocket;// 绑定到任意地址的 1234 端口if (udpSocket.bind(QHostAddress::AnyIPv4, 1234)) {qDebug() << "UDP socket bound to port 1234.";} else {qDebug() << "Failed to bind the UDP socket.";}return 0;
}

对于TCP客户端。 connectToHostQTcpSocket 类中的一个方法,用于建立 TCP 客户端与服务器之间的连接。它尝试将客户端套接字连接到指定的服务器 IP 地址和端口号。连接成功后,客户端可以通过该套接字与服务器进行数据通信。

#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>int main() {QTcpSocket tcpClientSocket;// 尝试连接到本地服务器的 1234 端口tcpClientSocket.connectToHost(QHostAddress::LocalHost, 1234);// 等待连接完成if (tcpClientSocket.waitForConnected(3000)) { // 等待 3 秒qDebug() << "Connected to server!";} else {qDebug() << "Failed to connect to server.";}return 0;
}

对于TCP服务端。listenQTcpServer 类中的一个方法,用于让服务器开始监听指定的地址和端口,等待客户端的连接请求。

#include <QTcpServer>
#include <QHostAddress>
#include <QDebug>int main() {QTcpServer tcpServerSocket;// 监听本机所有可用网络接口的 1234 端口if (tcpServerSocket.listen(QHostAddress::Any, 1234)) {qDebug() << "Server is listening on port 1234.";} else {qDebug() << "Failed to start server.";}return 0;
}

③数据接收

对于UDP。hasPendingDatagrams() 是 Qt 中 QUdpSocket 类的一个成员函数,用于检查是否有未处理的数据报等待读取。

#include <QTcpServer>
#include <QUdpSocket>class MyUDPReceiver : public QObject {Q_OBJECT
public:explicit MyUDPReceiver(QObject *parent = nullptr) : QObject(parent), udpSocket(new QUdpSocket(this)) {udpSocket->bind(1234); // 绑定到端口1234connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));}public slots:void readPendingDatagrams() {while (udpSocket->hasPendingDatagrams()) {QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress sender;quint16 senderPort;udpSocket->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort);qDebug() << "Received datagram:" << datagram<< "from" << sender.toString() << "port" << senderPort;}}private:QUdpSocket *udpSocket;
};

对于TCP客户端。readAll() 是 Qt 中 QTcpSocket 类的一个成员函数,用于从套接字中读取所有可用的数据 。

#include <QTcpSocket>class TcpClient : public QObject {Q_OBJECT
public:explicit TcpClient(QObject *parent = nullptr) : QObject(parent), tcpSocket(new QTcpSocket(this)) {tcpSocket->connectToHost("example.com", 1234);connect(tcpSocket, SIGNAL(connected()), this, SLOT(onConnected()));connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));}public slots:void onConnected() {if (tcpSocket->state() == QTcpSocket::ConnectedState) {qDebug() << "Connected to server.";}}void onReadyRead() {QByteArray data = tcpSocket->readAll();if (!data.isEmpty()) {qDebug() << "Received data:" << data;}}private:QTcpSocket *tcpSocket;
};

对于TCP服务端。bytesAvailable() 是 Qt 中 QAbstractSocket 类的一个成员函数,用于获取当前套接字中可用的数据字节数量

#include <QTcpServer>
#include <QTcpSocket>class TcpServer : public QObject {Q_OBJECT
public:explicit TcpServer(QObject *parent = nullptr) : QObject(parent), server(new QTcpServer(this)) {if (server->listen(QHostAddress::Any, 12345)) {qDebug() << "Server is listening on port 12345";} else {qDebug() << "Failed to start the server.";}connect(server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));}public slots:void onNewConnection() {QTcpSocket *client = server->nextPendingConnection();if (client) {qDebug() << "New client connected:" << client->peerAddress().toString();connect(client, SIGNAL(readyRead()), this, SLOT(onClientReadyRead(client)));}}void onClientReadyRead(QTcpSocket *client) {while (client->bytesAvailable() > 0) {QByteArray data = client->read(client->bytesAvailable());qDebug() << "Received from client:" << data;// 处理接收到的数据}}private:QTcpServer *server;
};

④数据发送

对于UDP。writeDatagram() 是 Qt 中 QUdpSocket 类的一个成员函数,用于向指定的目标地址和端口发送一个 UDP 数据报。

#include <QUdpSocket>
#include <QHostAddress>class UdpSender : public QObject {Q_OBJECT
public:explicit UdpSender(QObject *parent = nullptr) : QObject(parent), udpSocket(new QUdpSocket(this)) {}void sendDatagram() {QByteArray datagram = "Hello, UDP!";QHostAddress targetAddress("192.168.1.2"); // 目标地址quint16 targetPort = 12345; // 目标端口qint64 bytesWritten = udpSocket->writeDatagram(datagram, targetAddress, targetPort);if (bytesWritten == datagram.size()) {qDebug() << "Datagram sent successfully.";} else {qDebug() << "Failed to send datagram.";}}private:QUdpSocket *udpSocket;
};

对于TCP客户端、服务端。write() 是 Qt 中 QTcpSocket 类的一个成员函数,用于向 TCP 连接的另一端发送数据。这个函数在 TCP 客户端和服务器端都可以使用

#include <QTcpSocket>
#include <QCoreApplication>
#include <QDebug>class TcpClient : public QObject {Q_OBJECT
public:explicit TcpClient(QObject *parent = nullptr) : QObject(parent), tcpSocket(new QTcpSocket(this)) {tcpSocket->connectToHost("example.com", 12345);connect(tcpSocket, SIGNAL(connected()), this, SLOT(onConnected()));connect(tcpSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));}public slots:void onConnected() {if (tcpSocket->state() == QTcpSocket::ConnectedState) {qDebug() << "Connected to server.";QByteArray data = "Hello, Server!";qint64 bytesWritten = tcpSocket->write(data);if (bytesWritten == data.size()) {qDebug() << "Data sent successfully.";} else {qDebug() << "Failed to send data.";}}}void onError(QAbstractSocket::SocketError socketError) {qDebug() << "Socket error occurred:" << tcpSocket->errorString();}private:QTcpSocket *tcpSocket;
};

⑤日志保存

如果不存在logs文件夹则生成,以当天时间命名log日志文件。

void NetAssistant::save_log(QString text)
{QString log_path = "logs";QDir dir;if (!dir.exists(log_path)){bool res = dir.mkpath(log_path);if (res != true){QMessageBox::warning(this, "错误", "log 文件夹创建失败");return;}}QString filename = log_path + "\\" + QDateTime::currentDateTime().toString("yyyy-MM-dd") + ".log";QFile file(filename);if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {// 处理错误,例如弹出对话框通知用户return;}QTextStream textStream(&file);// 写入文本内容textStream << text << endl;// 关闭文件file.close();
}

4.打包成exe

 打开项目使用的编译器,然后cd到项目的release目录。使用一下命令打包成可执行文件

windeployqt xxx.exe

 如下所示,所有项目相关的dll文件都被移到当前文件下

四、效果展示

qt网络调试助手

五、总结


通过本文的详细讲解,我们完成了一个基于VS2022和Qt5的网络调试助手的开发。包括UDP、TCP等通信、收发数据、保存日志等功能。

在开发过程中,我们深入了解了QtNetWork的应用,通过它轻松实现了网络通信。同时,本文还详细介绍了如何在Qt中设计用户界面,使我们的工具不仅功能完善,而且使用起来简洁直观。

希望通过这篇文章,你能够更好地掌握Qt开发知识,并将这些技能应用到实际项目中。如果你在开发过程中遇到任何问题,欢迎在评论区交流讨论。

这篇关于基于VS2022+Qt5+C++的网络调试助手开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146370

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来