Qt/C++开源项目 TCP客户端调试助手(源码分享+发布链接下载)

devtools/2025/1/15 22:10:02/

这是一个TCP客户端调试助手,具有简洁直观的界面,用户能够方便地测试TCP协议的通信功能,并可同时作为客户端与服务器端使用。以下是该程序的功能特点及用途介绍:

功能特点:

  1. TCP客户端与服务器调试:支持同时作为TCP客户端和服务器端使用,方便进行本地和远程通信的调试。
  2. 连接状态监控:实时显示客户端和服务器的连接状态,帮助用户快速了解连接是否成功。
  3. 发送与接收数据:支持手动输入数据进行发送,能够清晰显示发送和接收的数据,帮助用户观察通信效果。
  4. 自动定时发送:具有自动发送功能,用户可以根据需要设置自动发送的时间间隔,用于测试持续发送的情况。
  5. HEX显示模式:提供十六进制模式显示发送和接收的数据,方便用户调试协议中的字节流。
  6. 多条定时发送指令:可预设多条指令进行定时发送,适合需要同时发送多组数据的场景。
  7. 清空缓存功能:提供一键清空接收缓存和发送缓存的功能,确保数据流的清晰可见性。
  8. 提示信息展示:通过不同颜色的提示信息,提醒用户连接状态、发送接收成功或失败等,便于迅速做出判断。

用途:

  • 网络通信调试:用于调试TCP/IP协议下的网络通信,适合网络设备开发、网络应用开发人员使用。
  • 协议验证:能够帮助验证通信协议的正确性,尤其是需要手动发送测试指令的场景。
  • 服务器负载测试:通过设置多条自动发送指令,可以用于初步测试服务器的负载能力。
  • 学习和测试工具:对网络编程和通信协议学习者来说,是一个很好的入门工具,可以直观地理解TCP通信机制。

下载链接:

通过百度网盘分享的文件:TCP调试助手.zip
链接:https://pan.baidu.com/s/1ItOuy6e8XgN1jw7lt-WYwA?pwd=cedu 
提取码:cedu

源码分享

#ifndef TCPCLIENTTHREAD_H
#define TCPCLIENTTHREAD_H#include <QThread>
#include <QTcpSocket>
#include <QMutex>
#include <QQueue>#define tc(a) QString::fromLocal8Bit(a)class TcpClientThread : public QThread
{Q_OBJECTpublic:explicit TcpClientThread(QObject *parent = nullptr);~TcpClientThread();void setServerInfo(const QString &host, int port);  // 设置服务器地址和端口void sendData(const QByteArray &data);              // 发送数据void stop();                                        // 停止线程signals:void clientConnected();     // 客户端连接信号void clientDisconnected();  // 断开连接信号void errors(int index, const QString &msg);         // 错误信号void warnings(int index, const QString &msg);       // 警告信号void informations(int index, const QString &msg);   // 信息信号void ClientInfor(const int flag, const QByteArray &msg); // 接收到的信息信号protected:void run() override;  // 重写线程的 run() 函数private slots:void onReadyRead();      // 处理数据读取void onDisconnected();   // 处理断开连接private:QTcpSocket *tcpSocket;   // TCP 套接字QString host;            // 服务器地址int port;                // 服务器端口QMutex mutex;            // 互斥锁,用于保护缓冲区QQueue<QByteArray> sendBuffer; // 发送缓冲队列bool m_run;          // 标志线程是否运行
};#endif // TCPCLIENTTHREAD_H
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QStandardItemModel>
#include "tcpclientthread.h"// 定义宏用于中文字符转换
#define tc(a) QString::fromLocal8Bit(a)QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
enum RunTimeStatus
{Error,            ///< 错误信息Warning,          ///< 警告信息Information,     ///< 常规信息
};
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void initStyle();//创建发送框void createSendLinEdit();private slots:void onClientConnected(); // 客户端连接信号槽void onClientDisconnected(); // 客户端断开信号槽void handleErrors(int index, const QString &msg);      // 处理错误信号槽void handleWarnings(int index, const QString &msg);    // 处理警告信号槽void handleInformations(int index, const QString &msg); // 处理信息信号槽void handlerClientInfor(const int flag,const QByteArray &data);void writeRunTimeMsgs(const QString &msg, const int level); // 输出运行时消息void on_clearRunTimeutton_clicked();void on_clearRecvButton_clicked();void on_closeTip_clicked();void on_connectedServerButton_clicked();void on_disconectedserverButton_clicked();void on_newOpenClient_clicked();void on_newOpenServer_clicked();private:Ui::MainWindow *ui;TcpClientThread *tcpClientThread;  // TCP 客户端线程
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QTextEdit>
#include <QFile>
#include <QProcess>
#include "timesendwidget.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow),tcpClientThread(new TcpClientThread(this))
{ui->setupUi(this);// 连接 TcpClientThread 的信号到 MainWindow 的槽connect(tcpClientThread, &TcpClientThread::clientConnected, this, &MainWindow::onClientConnected);connect(tcpClientThread, &TcpClientThread::clientDisconnected, this, &MainWindow::onClientDisconnected);connect(tcpClientThread, &TcpClientThread::errors, this, &MainWindow::handleErrors);connect(tcpClientThread, &TcpClientThread::warnings, this, &MainWindow::handleWarnings);connect(tcpClientThread, &TcpClientThread::informations, this, &MainWindow::handleInformations);connect(tcpClientThread, &TcpClientThread::ClientInfor, this, &MainWindow::handlerClientInfor);createSendLinEdit();initStyle();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::initStyle()
{//加载样式表QString qss;QFile file(":/qss/psblack.css");if (file.open(QFile::ReadOnly)) {
#if 1//用QTextStream读取样式文件不用区分文件编码 带bom也行QStringList list;QTextStream in(&file);//in.setCodec("utf-8");while (!in.atEnd()) {QString line;in >> line;list << line;}qss = list.join("\n");
#else//用readAll读取默认支持的是ANSI格式,如果不小心用creator打开编辑过了很可能打不开qss = QLatin1String(file.readAll());
#endifQString paletteColor = qss.mid(20, 7);qApp->setPalette(QPalette(paletteColor));qApp->setStyleSheet(qss);file.close();}}void MainWindow::createSendLinEdit()
{for(int i=0;i<10;i++){TimeSendWidget *sendWidget=new TimeSendWidget;connect(sendWidget,&TimeSendWidget::sendLineData,[=](const QByteArray &data ){if(data.isEmpty()){writeRunTimeMsgs(tc("信息为空,拒绝发送"),Warning);return ;}if(tcpClientThread)tcpClientThread->sendData(data);});ui->verticalLayout->addWidget(sendWidget);}
}// 处理客户端连接的槽函数
void MainWindow::onClientConnected()
{writeRunTimeMsgs(tc("客户端连接成功") , 2);ui->connectedServerButton->setEnabled(false);
}// 处理客户端断开的槽函数
void MainWindow::onClientDisconnected()
{writeRunTimeMsgs(tc("客户端断开连接"), 1);ui->connectedServerButton->setEnabled(true);
}// 处理错误信号
void MainWindow::handleErrors(int index, const QString &msg)
{Q_UNUSED(index);writeRunTimeMsgs(msg, Error);
}// 处理警告信号
void MainWindow::handleWarnings(int index, const QString &msg)
{Q_UNUSED(index);writeRunTimeMsgs( msg, Warning);
}// 处理信息信号
void MainWindow::handleInformations(int index, const QString &msg)
{Q_UNUSED(index);writeRunTimeMsgs(msg, Information);
}void MainWindow::handlerClientInfor(const int flag, const QByteArray &data)
{QString prefix;QString color;QString msg=tc("%1客户端: %3").arg(flag>0?tc("接收←"):tc("发送→")).arg(ui->isShowHexButton->isChecked()? data.toHex(' ').toUpper():QString::fromLocal8Bit(data));if(flag>0){//更新显示信息ui->recvByte->setValue(ui->recvByte->value()+data.size());ui->recvFram->setValue(ui->recvFram->value()+1);if(!ui->isShowRecvButton->isChecked())return;prefix = tc("【接收】");color = "#00ff00";}else{ui->sendByte->setValue(ui->sendByte->value()+data.size());ui->sendFram->setValue(ui->sendFram->value()+1);if(!ui->isShowSendButton->isChecked())return;prefix = tc("【发送】");color = "orange";}// 获取当前时间QString timestamp = ui->isShowTimeButton->isChecked()?QDateTime::currentDateTime().toString("hh:mm:ss(zzz)"):"";// 将消息插入到QTextEdit中并改变颜色// 将消息插入到QTextEdit中并改变颜色QString formattedMsg = QString("<span style='color:%1;'>%2 %3: %4</span>").arg(color, prefix, timestamp,msg);ui->receiveTextEdit->append(formattedMsg);
}// 输出运行时消息
void MainWindow::writeRunTimeMsgs(const QString &msg, const int level)
{QString prefix;QString color;// 获取当前时间QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");switch (level) {case 0: // 异常prefix = tc("【异常】");color = "red";break;case 1: // 警报prefix = tc("【警报】");color = "orange";break;case 2: // 提示prefix = tc("【提示】");color = "#00ff00";break;}// 将消息插入到QTextEdit中并改变颜色QString formattedMsg = QString("<span style='color:%1;'>%2 %3: %4</span>").arg(color, prefix, timestamp, msg);ui->outputTextEdit->append(formattedMsg);}void MainWindow::on_clearRunTimeutton_clicked()
{ui->outputTextEdit->clear();
}void MainWindow::on_clearRecvButton_clicked()
{ui->receiveTextEdit->clear();
}void MainWindow::on_closeTip_clicked()
{ui->groupBox->setVisible(!ui->groupBox->isVisible());
}void MainWindow::on_connectedServerButton_clicked()
{QString host = ui->hostLineEdit->text();int port = ui->portspinBox->text().toInt();if (!tcpClientThread->isRunning()){tcpClientThread->setServerInfo(host, port);tcpClientThread->start();  // 启动线程} else{// QMessageBox::warning(this, tc("警告"), tc("已经连接到服务器"));}
}void MainWindow::on_disconectedserverButton_clicked()
{if(tcpClientThread)tcpClientThread->stop();
}void MainWindow::on_newOpenClient_clicked()
{if (!QProcess::startDetached(QCoreApplication::applicationFilePath())) {writeRunTimeMsgs(tc("新客户端启动失败!"),Error);} else {writeRunTimeMsgs(tc("新客户端启动成功!"),Information);}}void MainWindow::on_newOpenServer_clicked()
{if (!QProcess::startDetached("QTcpServerDemo.exe")) {writeRunTimeMsgs(tc("新服务器启动失败!"),Error);} else {writeRunTimeMsgs(tc("新服务器启动成功!"),Information);}
}
#include "tcpclientthread.h"
#include <QHostAddress>
#include <QEventLoop>#define tc(a) QString::fromLocal8Bit(a)TcpClientThread::TcpClientThread(QObject *parent): QThread(parent), tcpSocket(nullptr), m_run(true)
{
}TcpClientThread::~TcpClientThread()
{stop();  // 停止线程wait();  // 等待线程结束
}void TcpClientThread::setServerInfo(const QString &host, int port)
{this->host = host;this->port = port;
}void TcpClientThread::run()
{tcpSocket = new QTcpSocket();connect(tcpSocket, &QTcpSocket::readyRead, this, &TcpClientThread::onReadyRead);connect(tcpSocket, &QTcpSocket::disconnected, this, &TcpClientThread::onDisconnected);// 连接到服务器tcpSocket->connectToHost(QHostAddress(host), port);if (tcpSocket->waitForConnected(3000)){emit clientConnected();emit informations(0, tc("已成功连接到服务器"));} else {emit errors(0, tc("连接服务器失败"));return;}m_run = true;QEventLoop eventLoop;  // 创建局部事件循环// 主循环,处理事件和发送数据while (m_run) {// 处理事件,防止阻塞信号槽eventLoop.processEvents(QEventLoop::AllEvents, 50);// 检查发送队列QMutexLocker locker(&mutex);if (!sendBuffer.isEmpty()){QByteArray dataToSend = sendBuffer.dequeue();if (tcpSocket->write(dataToSend) == -1){emit errors(1, tc("发送数据失败"));} else{emit ClientInfor(0,dataToSend);}}msleep(10);  // 避免占用过多CPU}// 断开连接if (tcpSocket->state() == QAbstractSocket::ConnectedState) {tcpSocket->disconnectFromHost();if (tcpSocket->state() != QAbstractSocket::UnconnectedState) {tcpSocket->waitForDisconnected(3000);}}tcpSocket->deleteLater();
}void TcpClientThread::stop()
{m_run = false;
}void TcpClientThread::sendData(const QByteArray &data)
{QMutexLocker locker(&mutex);  // 加锁保护sendBuffer.enqueue(data);  // 添加到发送队列
}void TcpClientThread::onReadyRead()
{QByteArray data = tcpSocket->readAll();emit ClientInfor(1, data);  // 发射接收到的数据信号
}void TcpClientThread::onDisconnected()
{emit clientDisconnected();
}


http://www.ppmy.cn/devtools/109855.html

相关文章

【北京迅为】《STM32MP157开发板使用手册》-第十六章 Buildroot制作根文件系统

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

stm32之SPI通信协议

文章目录 前言一、SPI通信协议1.1 SPI简介1.2 SPI通信特点1.3 SPI与I2C对比 二、SPI硬件电路三、SPI通信原理四、SPI时序单元4.1 起始和终止条件4.2 交换一个字节(模式1)4.3 交换一个字节(模式0)4.4 交换一个字节(模式2和3) 五、SPI时序5.1 发送指令5.2 指定地址写5.3 指定地址…

Python酷库之旅-第三方库Pandas(116)

目录 一、用法精讲 511、pandas.DataFrame.std方法 511-1、语法 511-2、参数 511-3、功能 511-4、返回值 511-5、说明 511-6、用法 511-6-1、数据准备 511-6-2、代码示例 511-6-3、结果输出 512、pandas.DataFrame.var方法 512-1、语法 512-2、参数 512-3、功能…

AI工具(不断更新)

AI工具 一、腾讯混元模型 https://yuanqi.tencent.com/agent-shop 腾讯元器&#xff0c;各种各样的agent 可以创建智能体agent&#xff0c;拿公司的规章制度去喂养&#xff0c;打造企业智能客服。 二、阿里通义千问 三、百度文心一言 四、文生图 五、文生视频 智谱&…

初识Verilog HDL其一

VerilogHDL是一种硬件描述语言&#xff0c;以文本形式来描述数字系统硬件的结构和行为的语言&#xff0c;用它可以表示逻辑电路图、逻辑表达式&#xff0c;还可以表示数字逻辑系统所完成的逻辑功能。 1.1 Verilog基础语法 1.11 逻辑值 0: 逻辑低电平&#xff0c;条件为假&am…

flutter开发多端平台应用的探索 上(基本操作)

前言 Flutter 是一个跨平台的开发框架&#xff0c;它允许开发者使用相同的代码库来构建 iOS、Android、Web 和桌面应用程序。 最近想了想&#xff0c;自己一直在用flutter开发特定端的应用&#xff0c;但是对于其他端的端特性case&#xff0c;如桌面端的菜单、多窗口、鼠标事…

学期计划大二上

项目方面&#xff1a; 等打完icpc再翻下数据再决定走哪个方向 算法方面&#xff1a; 感觉自己的代码能力还是不够&#xff0c;明明思路已经很清晰了代码还是写的很慢&#xff0c;所以在赛场上一直没有当键盘手的勇气&#xff0c;这也导致了赛场上的失利&#xff0c;我觉得我的…

计算机毕业设计选题推荐-果蔬生产溯源管理系统-Java/Python

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…