QT——TCP网络调试助手

目录

一.项目展示

​编辑

二.开发流程

三.QTcpServer、QTcpSocket、QUdpSocket类的学习

1.QTcpServer服务端

2.QTcpSocket客户端

3.Udp通信

四.网络调试助手

1.首先我们实现当用户选择不同协议类型时不同的UI组件如何切换

2.实现打开/关闭按键图片的切换

方式一:通过其父类所提供的void setIcon(const QIcon &icon)函数去实现

方式二:重写QPushButton的事件

3.定时发送

 4.实现代码如下


一.项目展示

二.开发流程

三.QTcpServer、QTcpSocket、QUdpSocket类的学习

Tcp面向连接的基于字节流的协议(点对点)

Udp面向无连接的基于报文的协议(一对一、一对多、多对多)

3.1QTcpServer类中包含以下函数

listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);用于监听

QTcpSocket nextPendingConnection();                        

从监听套接字中获取一个已准备好的客户端进行连接
deleteLater();

释放资源

disconnectFromHost(); 

断开连接

 QTcpServer类包含以下信号

newConnection();监听到有新的连接时
acceptError(QAbstractSocket::SocketError socketError);尝试接受新的连接时发生错误

 3.2QTcpSocket类包含以下函数

connectToHost(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);连接服务端

QHostAddress peerAddress();

获取ip地址
quint16 clientPort();获取端口号
readall();读取消息
write(QByteArray data);发送数据
state();判断当前状态,如:if(socket->state== QAbstractSocket::ConnectedState)
deleteLater();释放资源

 QTcpSocket类包含以下信号

connected();成功连接
readyRead();有新的数据发来时
disconnected();断开连接时

3.3QUdpSocket类包含以下函数

bind(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);绑定ip地址和端口,接受数据时使用
bool hasPendingDatagrams() const;用于检查是否有待处理的数据报。返回 true: 表示有一个或多个待处理的数据报
pendingDatagramSize();通常用于设置接受缓冲区的大小时使用,返回下一个待处理的数据报的大小
readDatagram(buffer.data(), buffer.size(), &sender, &senderPort); 将接收到的数据存储到提供的缓冲区中
writeDatagram(<要发送的数据>, <ip地址>, <端口号>); ip为QHostAddress::Broadcast代表广播发送
close();关闭udp套接字
deleteLater();释放资源

 QUdpSocket类包含以下信号

readyRead();有新的数据发来时

3.4以下程序可获取本地ip地址

// 获取本地主机名称
QString localHostName = QHostInfo::localHostName(); // 根据本地主机名称获取本地主机信息
QHostInfo info = QHostInfo::fromName(localHostName); // 将本地主机的所有 IP 地址赋值给容器中
QList<QHostAddress> addresses = info.addresses(); // 清空 comboBox_2 并添加 IPv4 地址
ui->comboBox_2->clear(); 
for (const auto& address : addresses) {if (address.protocol() == QAbstractSocket::IPv4Protocol) {qDebug() << "IPv4 Address:" << address.toString();ui->comboBox_2->addItem(address.toString());}
}

1.QTcpServer服务端

QTcpServer* server = new QTcpServer(this);               //创建一个监听套接字
server->listen();                                        //开始监听指定ip与端口connect(server, &QTcpServer::newConnection, this, [=](){ //信号与槽连接:当监听到有新的连接时QTcpSocket* clientSocket;                            //创建一个网络套接字clientSocket = server->nextPendingConnection();      //从监听套接字中获取一个已准备好的客户端进行连接//获取客户端的ip与端口号QHostAddress clientAddress = clientSocket->peerAddress();quint16 clientPort = clientSocket->peerPort();//信号与槽连接:当有新的消息时connect(clientSocket, &QTcpSocket::readyRead, this, [=](){QByteArray data = clientSocket->readAll();       //读取消息);//信号与槽连接:当客户端断开连接时connect(clientSocket, &QTcpSocket::disconnected, this, [=](){clientPort->deleteLater();                       //释放资源);if(clientSocket->state() == QAbstractSocket::ConnectedState){cnt = clientSocket->write(arrayData);}
);server->close();                                         //关闭服务端

2.QTcpSocket客户端

QTcpSocket* socket = new QTcpSocket(this);
connect(socket, &QTcpSocket::connected, this, [=]() {       //客户端连接到服务端槽函数//...
});connect(socket, &QTcpSocket::readyRead, this, [=]() {       //客户端接收到数据槽函数int sum = 0;QByteArray data = socket->readAll();                    //读取接收到的数据sum = data.size();
}connect(socket, &QTcpSocket::disconnected, this, [=]() {    //客户端与服务端断开连接槽函数qDebug() << "Disconnected from server.";socket->deleteLater();                                  //断开连接时删除 socket
});if(socket->state() == QAbstractSocket::ConnectedState){     //客户端发送数据socket->write(arrayData);
}socket->connectToHost(remIpaddress, remPort);               //尝试连接服务端socket->disconnectFromHost();                               //主动断开与客户端的连接
socket->deleteLater();                                      //释放资源

3.Udp通信

QUdpSocke* udp = new QUdpSocket(this);                   
udp->bind(ipaddress, honts.toInt();             //接受数据时使用,绑定ip地址和端口//绑定信号与槽,当接收到数据时 
connect(udp, &QUdpSocket::readyRead, this, [=](){                                               while (udp->hasPendingDatagrams()) {        //检查是否有待处理的数据报,循环读取QByteArray buffer;buffer.resize(int(udp->pendingDatagramSize()));   //确保接收缓冲区大小合适QHostAddress sender;                    //发送者的地址quint16 senderPort;                     //发送者的端口//读取数据并存入buffer中udp->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort); }
);udp->writeDatagram(<要发送的数据>, <ip地址>, <端口号>); QHostAddress broadcastAddress = QHostAddress::Broadcast;                     // 设置广播地址
qint64 bytesWritten = con->writeDatagram(arrayData, broadcastAddress, port); // 发送广播udp->close();                                      
udp->deleteLater();                                

四.网络调试助手

1.首先我们实现当用户选择不同协议类型时不同的UI组件如何切换

绑定信号&QComboBox::currentIndexChangedQComBobox组件,当QComboBox组件的索引变化时,执行下面槽函数,实现不同的UI组件之间的切换

void Widget::on_CurrentIndexChanged() {// 获取用户当前选择的索引currentIndex = ui->comboBox_1->currentIndex();// 删除垂直布局中的第六个组件(如果存在)if (ui->verticalLayout->count() >= 6) {QWidget* widget = ui->verticalLayout->itemAt(5)->widget(); // 获取第六个控件if (widget) {ui->verticalLayout->removeWidget(widget);   // 从布局中移除widget->deleteLater();                       // 删除组件}}// 根据选择的索引更新界面if (currentIndex == 1) {  // 用户选择了客户端ui->label_2->setText("(2)本地主机地址");ui->label_3->setText("(3)远程主机地址");box = new QComboBox(this);                    // 创建新的 QComboBoxbox->addItem("192.168.56.1 :8080");           // 向组件中添加内容box->setEditable(true);                        // 设置组件中的内容可修改ui->verticalLayout->addWidget(box);            // 将组件添加到垂直布局中box->show();                                   // 显示新创建的 QComboBox} else if (currentIndex == 0) {  // 用户选择了UDPui->lineEdit_rev->setText("192.168.238.1");ui->lineEdit_revHonts->setText("8080");ui->label_2->setText("(2)本地主机地址");ui->label_3->setText("(3)本地主机端口");edt = new QLineEdit(this);                     // 创建新的 QLineEditedt->setText("8080");                          // 设置新的 QLineEdit 显示的内容ui->verticalLayout->addWidget(edt);            // 将组件添加到垂直布局中edt->show();                                   // 显示新创建的 QLineEdit} else {  // 用户选择了服务端ui->label_2->setText("(2)本地主机地址");ui->label_3->setText("(3)本地主机端口");edt = new QLineEdit(this);                     // 创建新的 QLineEditedt->setText("8080");                          // 设置新的 QLineEdit 显示的内容ui->verticalLayout->addWidget(edt);            // 将组件添加到垂直布局中edt->show();                                   // 显示新创建的 QLineEdit}
}

2.实现打开/关闭按键图片的切换

方式一:通过其父类所提供的void setIcon(const QIcon &icon)函数去实现

const QString ICON_PATH_MM = ":/pictures/mm.png"; // 图标路径常量
const QString ICON_PATH_PP = ":/pictures/pp.png"; // 图标路径常量Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->pushButton->setCheckable(true);// 设置按钮透明背景ui->pushButton->setStyleSheet("QPushButton {""background-color: transparent;""border: none;" // 可选:去掉按钮边框"}");// 设置图标和大小setButtonIconAndSize(ICON_PATH_MM);
}void Widget::on_pushButton_clicked(bool checked)
{// 根据按钮的 checked 状态切换图标setButtonIconAndSize(checked ? ICON_PATH_PP : ICON_PATH_MM);
}// 封装设置图标和大小的逻辑
void Widget::setButtonIconAndSize(const QString &iconPath)
{QSize buttonSize = ui->pushButton->size(); // 获取按钮的当前大小ui->pushButton->setIconSize(buttonSize);   // 设置图标大小ui->pushButton->setIcon(QIcon(iconPath));  // 设置图标
}

方式二:重写QPushButton的事件

bool t = true;myBtnOpen::myBtnOpen(QWidget *parent):QPushButton(parent)
{// 加载初始图片pic.load(":/pictures/mm.png");// 设置按钮的固定大小为图片的大小//setFixedSize(pic.size());//setFixedSize(100,100);// 刷新界面,触发 paintEvent 进行绘制update();
}void myBtnOpen::paintEvent(QPaintEvent *e)
{// 创建一个 QPainter 对象,负责绘制图片QPainter painter(this);// 使用 QPainter 在按钮区域内绘制当前加载的图片painter.drawPixmap(rect(), pic);
}void myBtnOpen::mousePressEvent(QMouseEvent *e)
{if(e->button() == Qt::LeftButton){//打开if(t == true){pic.load(":/pictures/mm.png");update();t = false;}else{pic.load(":/pictures/pp.png");update();t = true;}}QPushButton::mousePressEvent(e);
}

3.定时发送

通过定时器实现,当用户勾选定时发送组件时

1.初始化定时器,设置定时器定时时间,启动定时器。

2.在构造函数中绑定定时器的超时信号与槽函数,通过Lambda表达式调用发送函数既可以

//定时发送槽函数
void Widget::on_checkBox_10_clicked(bool checked)
{if(checked){//设置定时器定时时间timer->setInterval(ui->lineEdit_msData->text().toInt());//启动定时器timer->start();}else{//停止定时器timer->stop();}
}
//发送按键槽函数
void Widget::on_pushButton_send_clicked()
{//(1)先获取用户输入的要发送的内容QString data = ui->textEdit_sendData->toPlainText();QByteArray arrayData = data.toLocal8Bit();int cnt = 0;//(2)判断Hex发送是否勾选,此处为勾选if (ui->checkBox_9->isChecked()) {// a.检查字节数是否是偶数if (0 != arrayData.size() % 2) {ui->label_state->setText("input error!");return;}// b.检查是否符合Hex表达for (char c : arrayData) {if (!isxdigit(c)) {ui->label_state->setText("input error!");return;}}// c.转化为16进制arrayData = QByteArray::fromHex(arrayData);}//(3).开始发送if (t == 1) {        // 客户端发送数据cnt = socket->write(arrayData);} else if (t == 2) { // 服务端发送数据cnt = clientSocket->write(arrayData);}//(4)判断是否发送成功if (cnt == -1) {ui->label_state->setText("send error!");} else {if (ui->checkBox_8->isChecked()) {ui->textEdit_sendData->clear();}sendCnt += cnt;ui->label_state->setText("send OK!");ui->label_sendCnt->setText("发送: " + QString::number(sendCnt));}
}

 4.实现代码如下

tunnek/mi (github.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/476.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

怎么压缩pdf文件大小?关于压缩PDF文件大小的几种压缩方法

怎么压缩pdf文件大小&#xff1f;压缩PDF文件能够显著减小文件体积&#xff0c;从而节省硬盘和云存储空间&#xff0c;这对于管理大量文档尤其重要。较小的文件大小使得通过电子邮件或在线平台发送变得更加迅速&#xff0c;缩短了传输时间。同时&#xff0c;压缩后的文件更方便…

使用Scrapy框架爬取博客信息

随着网络的发展&#xff0c;越来越多有价值的信息存储在网络上。使用爬虫技术可以从这些信息源中提取出有用的数据。本文将介绍如何使用Python中的Scrapy框架来爬取博客站点上的文章标题、作者以及阅读数&#xff0c;并将其保存到JSON文件中。 一、项目背景 Scrapy是一个快速…

网络编程 UDP编程 Linux环境 C语言实现

UDP编程 1. 一般UDP编程 UDP传输特点&#xff1a;非面向连接、不可靠的、无序的 报式传输 支持组播和广播 UDP应用数据最大长度建议&#xff1a;MTU(以太网分组数据的最大长度)1500 - 20(IP头) - 8(UDP头) 1472Bytes 客户端&#xff1a;支持两种形式的代码编写: 1. 不定向…

使用linux+nginx 作为unity webgl的服务器

使用linuxnginx 作为unity webgl的服务器 建议使用命令行下载&#xff0c;使用源码编译可能编译不过。 自己创建一个uinty webgl项目&#xff0c;或者下载我上传的unity webgl项目 https://download.csdn.net/download/GoodCooking/24339451下载nginx 使用图形界面 下载ngi…

Flink CDC 同步 Mysql 数据

文章目录 一、Flink CDC、Flink、CDC各有啥关系1.1 概述1.2 和 jdbc Connectors 对比 二、使用2.1 Mysql 打开 bin-log 功能2.2 在 Mysql 中建库建表准备2.3 遇到的坑2.4 测试 三、番外 一、Flink CDC、Flink、CDC各有啥关系 Flink&#xff1a;流式计算框架&#xff0c;不包含 …

【模型学习之路】手写+分析bert

手写分析bert 目录 前言 架构 embeddings Bertmodel 预训练任务 MLM NSP Bert 后话 netron可视化 code2flow可视化 fine tuning 前言 Attention is all you need! 读本文前&#xff0c;建议至少看懂【模型学习之路】手写分析Transformer-CSDN博客。 毕竟Bert是tr…

C#实现隐藏和显示任务栏

实现步骤 为了能够控制Windows任务栏&#xff0c;我们需要利用Windows API提供的功能。具体来说&#xff0c;我们会使用到user32.dll中的两个函数&#xff1a;FindWindow和ShowWindow。这两个函数可以帮助我们找到任务栏窗口&#xff0c;并对其执行显示或隐藏的操作 引入命名空…

Excel菜单选项无法点击?两种原因及解决方法全解析

在使用Excel处理数据时&#xff0c;有时会遇到菜单选项无法点击的情况。这种问题会影响到正常的操作和编辑。出现这种情况的原因可能有多种&#xff0c;本文将介绍两种常见的原因&#xff0c;并提供相应的解决方法&#xff0c;帮助小伙伴们快速恢复菜单选项的正常使用。 原因一…

SpringBoot节奏:Web音乐网站构建手册

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

波尼音乐 2.3.0-b1 | 开源免费的音乐播放器,附两个公共接口

波尼音乐最初作为一个毕设项目&#xff0c;凭借其实现了本地与网络音乐播放的能力而受到许多用户的喜爱。随着百度在线音乐API的关闭&#xff0c;波尼音乐逐渐失去在线音乐播放功能。在开源社区的支持下&#xff0c;开发者发现新的网易云音乐API&#xff0c;重启项目并进行全面…

ComfyUI - ComfyUI 工作流中集成 SAM2 + GroundingDINO 处理图像与视频 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143359538 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 SAM2 与…

C++原创游戏宝强越狱第二季即将回归

抱歉&#xff0c;3个月以来我不是没时间更&#xff0c;而是懒得更。。。 这不宝强越狱第一季完结了么&#xff0c;所以我决定两个月内弄完宝强越狱第二季&#xff0c;第一个版本将在2025年1月1日发布。不过&#xff0c;我还做了个预告片BQYY预告片-CSDN直播&#xff08;33s的垃…

mysql查表相关练习

作业要求&#xff1a; 单表练习&#xff1a; 1 . 查询出部门编号为 D2019060011 的所有员工 2 . 所有财务总监的姓名、编号和部门编号。 3 . 找出奖金高于工资的员工。 4 . 找出奖金高于工资 40% 的员工。 5 找出部门编号为 D2019090011 中所有财务总监&#xff0c;和…

【笔试题】迈入offer的新大门

1. 笔试题1 1.1 题目链接&#xff1a;[NOIP2010]数字统计_牛客题霸_牛客网 1.2 题目描述 补充&#xff1a; 1.3 解法 1.3.1 算法思路 定义变量&#xff0c;L,R,count用于记数。 对规定符合区域范围内的数据进行遍历&#xff0c;对每个数据的每一位进行判断是否为2&#xf…

Gitee push 文件

1、背景 想将自己的plecs仿真放到git中管理&#xff0c;以防丢失&#xff0c;以防乱改之后丢失之前版本仿真。此操作说明默认用户已下载git。 2、操作步骤 2.1 开启Git Bash 在文件夹中右键&#xff0c;开启Git Bash。 2.2 克隆文件 在Git Bash中打git clone git地址&#…

【AIGC】2024-arXiv-Lumiere:视频生成的时空扩散模型

2024-arXiv-Lumiere: A Space-Time Diffusion Model for Video Generation Lumiere&#xff1a;视频生成的时空扩散模型摘要1. 引言2. 相关工作3. Lumiere3.1 时空 U-Net (STUnet)3.2 空间超分辨率的多重扩散 4. 应用4.1 风格化生成4.2 条件生成 5. 评估和比较5.1 定性评估5.2 …

MySQL高可用MHA

目录 一、MHA概述 1.MHA是什么 2.MHA的组成 3.MHA特点 4.MHA工作原理 二、MySQL部署MHA 1.配置主从复制 2.配置MHA高可用 2.1所有服务器安装MHA依赖环境 2.2所有服务器上安装node组件 2.3在MHA manager节点上安装manager组件 2.4在所有服务器上配置无密码认证 …

聚类算法综述

摘要 聚类算法旨在根据数据中的固有模式和相似性将数据组织成组或簇。它们在当今生活中扮演着重要角色&#xff0c;例如在市场营销和电子商务、医疗保健、数据组织和分析以及社交媒体中。现有众多聚类算法&#xff0c;并且不断有新的算法被引入。每个算法都有其自身的优点和缺…

【网络监控加速设备】国产化一站式高性能数据处理平台(海光CPU+复旦微FPGA)

随着网络流量的飞速增长&#xff0c;数据的监控与管理需求日益加剧。针对这一痛点&#xff0c;一款集协议检测、数据监测、报文转发和结果展示于一体的网络监控加速设备&#xff0c;设备百分之百国产化也体现了完全自主可控。设备不仅具备丰富的网络监控功能&#xff0c;还支持…

确保企业架构与业务的一致性与合规性:数字化转型中的关键要素与战略实施

在现代企业的数字化转型过程中&#xff0c;确保企业架构&#xff08;Enterprise Architecture, EA&#xff09;与企业业务的紧密一致性与合规性至关重要。无论是在战略层面还是运营层面&#xff0c;EA都为企业的未来发展提供了清晰的蓝图&#xff0c;确保企业在应对复杂的业务环…