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

news2024/11/16 1:50:59

这是一个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_OBJECT

public:
    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_OBJECT

public:
    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());
#endif
        QString 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.coloradmin.cn/o/2110825.html

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

相关文章

C++11 --- 可变参数模板

序言 不知道大家有没有细细研究过在 C 语言 中的 printf 函数&#xff0c;也许我们经常使用他&#xff0c;但是我们可能并不是那么了解他。先看一下调用格式&#xff1a;int printf ( const char * format, ... );&#xff0c;在这里的 format 代表我们的输出格式&#xff0c;后…

若依库存管理 ruoyi-wms V2.0发布:升级到jdk17和vue3,支持一物一码

开源地址 https://gitee.com/zccbbg/wms-ruoyi 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可 活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源 若依wms是一套基于若依的wms仓库管理系统&#xff0c;支持lodop和网页…

Windows环境虚拟机安装

一、软件安装 1. vmware官网地址 点进去选这个products 然后往下滑选这个查看桌面虚拟机管理程序 然后点击这个桌面虚拟机管理程序 然后下拉找到download now下载 然后会跳转到broadcom网站&#xff0c;选择注册账号,这里我是使用谷歌邮箱注册的 注册完之后点击这个链接&…

【LeetCode】07.整数反转

题目要求 解题思路 这道题的难点在于怎么判断越界&#xff0c;我们无法直接与最大值或最小值比较&#xff0c;但是由于每一次我们的ret都需要乘10这个特性来使用ret与最大值或最小值除10进行比较 代码实现 class Solution { public:int reverse(int x) {int ret0;while(x){…

JS生成二维码QRCode代码

JavaScript是一种广泛使用的前端编程语言&#xff0c;它不仅用于网页交互&#xff0c;还可以实现许多实用功能&#xff0c;如生成二维码。本篇文章将深入探讨如何使用JavaScript生成二维码&#xff0c;以及如何确保这种生成的二维码在各种浏览器和手机端都能正常工作&#xff0…

C语言-程序环境 #预处理 #编译 #汇编 #链接 #执行环境

文章目录 前言 一、程序的环境翻译和执行环境 二、翻译环境 (一)、整体把握 (一)、编译 1、预处理(预编译) 2、编译 a、词法分析 b、语法分析 c、语义分析 d、符号汇总 3、汇编 (二)、链接 三、运行环境 总结​​​​​​​ 前言 路漫漫其修远兮&#xff0c;吾将…

波导模式分析2 用于圆TE01模式高功率传输线的大型多模波导滤波器

摘要&#xff1a; 一种对于大型多模波导滤波器的设计方法&#xff0c;其能衰减掉&#xff08;deteriorate&#xff09;不想要的模式而不影响所需要的工作模式&#xff0c;被提出来抑制用于圆TE01模式高功率传输线的受限模式谐振。为了从TE10模式中分离出不期望的模式&#xff…

【蓝桥杯嵌入式(二)Led、Key、Lcd】

蓝桥杯嵌入式&#xff08;二&#xff09;Led、Key、Lcd 五、Led模块1.原理图配置2. 知识点3.底层代码 六、Key模块1.原理图配置2.知识点3.底层代码底层代码&#xff08;四⾏代码版本&#xff09;底层代码&#xff08;状态机版本&#xff09; 七、LCD模块1.原理图配置2.知识点底…

文章改写工具,帮你进行文章修改润色提升文章质量

在文字的世界里&#xff0c;每一篇文章都是创作者心灵的结晶。然而&#xff0c;即使是经验丰富的作家&#xff0c;也难免会在创作过程中遇到表达上的瓶颈。此时&#xff0c;文章改写工具便显得尤为重要&#xff0c;它以其独特的功能&#xff0c;对文章进行精准的修改与润色&…

机器学习算法那些事 | Plotly Express:一种简洁且强大的可视化神器

本文来源公众号“机器学习算法那些事”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;Plotly Express&#xff1a;一种简洁且强大的可视化神器 Plotly Express 是 Python 交互式库 Plotly 的高级组件&#xff0c;受 Seaborn 和 g…

全国机器人大赛 Robocon 常州工学院团队首战国三

全国机器人大赛 Robocon 常州工学院团队首战国三 通宵7天7夜&#xff0c;常州工学院RC团队&#xff0c;首次闯入全国机器人大赛国赛&#xff0c;并成功得分&#xff01; 不同于老牌强队&#xff0c;常州工学院&#xff08;下面用"常工"代替&#xff09;的这只队伍&…

Java题集(由入门到精通)03

此系列文章收录大量Java经典代码题&#xff08;也可以算是leetcode刷题指南&#xff09;&#xff0c;希望可以与大家一起努力学好Java。3、2、1&#xff0c;请看&#xff01; 目录 1.创建学生成绩表 2.冒泡排序 3.模拟彩票中奖 4.杨辉三角 1.创建学生成绩表 输入n个学生的…

【学习笔记】SSL证书安全机制之证书撤销

前言&#xff1a;以往提到过&#xff0c;钓鱼网站会仿冒我们&#xff0c;如果我们的私钥泄露了&#xff0c;如果被不法分子得到了私钥&#xff0c;他们就能假装是我们网站。那现在&#xff0c;我们要做的是生成新私钥并申请新证书。问题来了&#xff0c;旧的证书亦然存在且有效…

胶条的回弹状态检测 仅需一台回弹测试仪

胶条的回弹状态检测之所以重要&#xff0c;主要基于以下几个方面的考虑&#xff1a; 一、保证产品功能性和密封性 密封效果&#xff1a;胶条作为密封元件&#xff0c;其回弹性能直接关系到密封效果的好坏。 耐久性&#xff1a;如果回弹性能不佳&#xff0c;容易出现永久性变形&…

8个txt自动化脚本,一定有你用得上的!Python如何读取txt文件数据!

这次和大家分享txt办公自动化&#xff0c;包括读取、对比、过滤、合并、转换格式、提取数据、统计词频、生成报告等。 分享一份Python学习大礼包&#xff08;激活码安装包、Python web开发&#xff0c;Python爬虫&#xff0c;Python数据分析&#xff0c;人工智能、自动化办公等…

GAMES101(0~1作业)

搭建虚拟机环境 安装Oracle VM VirtualBox虚拟机&#xff0c;安装虚拟硬盘&#xff0c;配置Linux Ubuntu-64 bit系统&#xff0c;启动虚拟机&#xff0c;发生冲突错误&#xff1a; 将Vmware虚拟设备取消挂起状态&#xff0c;关机确保 Hyper-V 完全关闭&#xff1a;bcdedit /se…

Pandas DataFrame的多级列索引导出到Excel时,如何避免空白行和列

我想将multi-header数据框保存为Excel文件。以下是示例代码&#xff1a; import pandas as pd import numpy as npheader pd.MultiIndex.from_product([[location1,location2],[S1,S2,S3]],names[loc,S])df pd.DataFrame(np.random.randn(5, 6), index[a,b,c,d,e], columnsh…

Python 中的 11 种经典时间序列预测方法(备忘单)

摘要: 本文演示了 11 种不同的经典时间序列预测方法,这些方法包括: 自回归(AR) 移动平均线 (MA) 自回归移动平均线 (ARMA) 自回归综合移动平均线 (ARIMA) 季节性自回归综合移动平均线 (SARIMA) 季节性自回归综合移动平均线与外生回归量... 本文演示了 11 种不同的经典时间序…

sheng的学习笔记-AI-半监督聚类

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 半监督学习&#xff1a;sheng的学习笔记-AI-半监督学习-CSDN博客 聚类&#xff1a;sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 均值算法&#xff1a;sheng的学习笔记-AI-K均值算法_k均值算法怎么算迭代两次后的最大…

掌握Git分支管理策略:让团队协作更高效

在现代软件开发过程中&#xff0c;版本控制系统&#xff08;VCS&#xff09;是不可或缺的一部分。Git作为目前最流行的分布式版本控制系统之一&#xff0c;为开发者提供了强大的工具集来管理代码变更历史。然而&#xff0c;仅仅掌握Git的基本命令并不足以应对大型项目和团队协作…