一、环境介绍
操作系统: win10 64位
QT版本: QT5.12.6
编译器: MinGW 32
TCP网络调试助手,在网络相关开发、嵌入式开发里使用较多,主要用来测试网络传输,调试等等。
这个版本设计的比较早,没有加入多线程处理连接上来的客户端,一般的调试场景已经满足。对于基本的QT网络开发入门学习借鉴已经足够了。
软件下载: https://download.csdn.net/download/xiaolong1126626497/17044958
二、效果图
三、源代码
3.1 widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowIcon(QIcon(":/image/14g.png")); //设置图标
SetStyle(":/qss/blue.css"); //设置样式表
setWindowTitle("TCP网络调试助手_v2.2 2020年7月11日");
comboBox_config();
timer = new QTimer(this); //创建定时器
connect(timer, SIGNAL(timeout()), this, SLOT(update())); //关联槽函数
/*控件名字设置*/
ui->checkBox_ShowTime->setText("接收时间显示");
ui->checkBox_TxBit->setText("自动发送附加位\\r\\n");
ui->checkBox_LoopTx->setText("循环发送数据");
ui->label_4->setText("设置循环间隔ms时间:");
ui->pushButton_connect->setText("连接");
ui->pushButton_SendData->setText("发送");
ui->About->setText("帮助");
ui->label->setText("1.协议类型");
ui->label_ip->setText("2.本地IP地址");
ui->label_prot->setText("3.本地端口");
ui->label_SendCnt->setText("TX");
ui->label_RxCnt->setText("RX");
ui->pushButton_clear->setText("复位");
ui->plainTextEdit_ShowData->setReadOnly(true);
ui->pushButton_cleanShow->setText("清除显示");
}
//设置指定样式
void Widget::SetStyle(const QString &qssFile) {
QFile file(qssFile);
if (file.open(QFile::ReadOnly)) {
QString qss = QLatin1String(file.readAll());
qApp->setStyleSheet(qss);
QString PaletteColor = qss.mid(20, 7);
qApp->setPalette(QPalette(QColor(PaletteColor)));
file.close();
}
}
//基本配置
void Widget::comboBox_config()
{
/*第一部分:网络设置*/
//1.1 配置协议
ui->comboBox_protocol->addItem("TCP Server");
ui->comboBox_protocol->addItem("TCP Client");
//1.2. 获取并配置本地IP地址
QList<QHostAddress> list = QNetworkInterface::allAddresses();
for(int i=0;i<list.count();i++)
{
QHostAddress addr=list.at(i);
if(addr.protocol() == QAbstractSocket::IPv4Protocol)
{
ui->comboBox_ipaddress->addItem(addr.toString());
}
}
//1.3 设置可编辑性
ui->comboBox_ipaddress->setEditable(true);
//1.4. 设置默认端口号
ui->lineEdit_prot->setText("8080");
/*第二部分:发送设置*/
//2.1设置循环发送时间
ui->lineEdi_LoopTime->setText("1000");
//2.2 设置默认发送的内容
ui->lineEdit_InputTxDtat->setText("https://blog.csdn.net/xiaolong1126626497");
//接收数量置0
TxCount=0;
RxCount=0;
/*第三部分:选择客户端时用于显示本地端口和IP*/
ClientShowLocalProtLabel =new QLabel("本地端口:");
ClientShowLocalIptLabel =new QLabel("本地IP地址:");
ClientEditProt= new QLineEdit;
ClientEditIP= new QLineEdit;
ClientLayout = new QHBoxLayout;
ClientLayout->addWidget(ClientShowLocalIptLabel);
ClientLayout->addWidget(ClientEditIP);
ClientLayout->addWidget(ClientShowLocalProtLabel);
ClientLayout->addWidget(ClientEditProt);
/*第四部分:选服务器时用于显示已经连接的客户端*/
SaverShowLocalProtLabel =new QLabel("已连接的客户端列表:");
ClientComboBoxList=new QComboBox;
ClientComboBoxList->setMinimumWidth(180);
ServerLayout = new QHBoxLayout;
ServerLayout->addWidget(SaverShowLocalProtLabel);
ServerLayout->addWidget(ClientComboBoxList);
ServerLayout->addStretch();
}
Widget::~Widget()
{
timer->stop(); //停止定时器
delete timer;
delete ui;
}
//创建服务器或者连接到服务器
void Widget::on_pushButton_connect_clicked()
{
if(ui->pushButton_connect->text()=="连接")
{
switch(ui->comboBox_protocol->currentIndex())
{
case 0: //服务器模式
NewServer();
break;
case 1: //客户端模式
NewClinet();
break;
}
}else
{
switch(ui->comboBox_protocol->currentIndex())
{
case 0: //服务器模式
ui->pushButton_connect->setText("连接");
for(int i=0;i<TcpFarClientList.count();i++)
{
TcpFarClientList.at(i)->close();
TcpFarClientList.removeAt(i);
}
LocalTcpServer->close();//关闭服务器
//取消客户端列表显示
ui->verticalLayout_9->removeItem(ServerLayout);
ClientComboBoxList->close();
SaverShowLocalProtLabel->close();
//断开服务器之后设置控件可用性
//创建服务器之后设置控件可用
ui->comboBox_ipaddress->setEnabled(true);
ui->comboBox_protocol->setEnabled(true);
ui->lineEdit_prot->setEnabled(true);
break;
case 1: //客户端模式
LocalTcpClientSocket->close();
break;
}
}
}
//服务器模式:创建服务器
void Widget::NewServer()
{
/*1. 实例化服务器*/
LocalTcpServer= new QTcpServer;
/*2. 设置监听的端口和IP地址*/
quint16 port=QString(ui->lineEdit_prot->text()).toInt();
if(ui->comboBox_ipaddress->currentText()=="QHostAddress::Any")
{
LocalTcpServer->listen(QHostAddress::Any,port);
}else
{
QHostAddress addr(ui->comboBox_ipaddress->currentText());
LocalTcpServer->listen(addr,port);
}
/*3. 关联连接信号,检测是否有新的客户端连接*/
connect(LocalTcpServer,SIGNAL(newConnection()),this,SLOT(NewTcpConnection()));
ui->pushButton_connect->setText("断开连接");
//添加布局,显示已经连接的客户端列表
ui->verticalLayout_9->insertLayout(1,ServerLayout);
ClientComboBoxList->show();
SaverShowLocalProtLabel->show();
//创建服务器之后设置控件可用
ui->comboBox_ipaddress->setEnabled(false);
ui->comboBox_protocol->setEnabled(false);
ui->lineEdit_prot->setEnabled(false);
}
//客户端模式:创建客户端
void Widget::NewClinet()
{
/*1. 创建本地客户端TCP套接字*/
LocalTcpClientSocket = new QTcpSocket;
/*2. 设置服务器IP地址*/
QString Ipaddr=ui->comboBox_ipaddress->currentText();
QHostAddress FarServerAddr(Ipaddr);
/*3. 连接客户端的信号槽*/
connect(LocalTcpClientSocket,SIGNAL(connected()),this,SLOT(LocalTcpClientConnectedSlot()));
connect(LocalTcpClientSocket,SIGNAL(disconnected()),this,SLOT(LocalTcpClientDisconnectedSlot()));
connect(LocalTcpClientSocket,SIGNAL(readyRead()),this,SLOT(LocalTcpClientReadDtatSlot()));
/*4. 尝试连接服务器主机*/
int prot=ui->lineEdit_prot->text().toInt();
LocalTcpClientSocket->connectToHost(FarServerAddr,prot);
}
//客户端模式:响应连接上服务器之后的操作
void Widget::LocalTcpClientConnectedSlot()
{
//显示本地端口和IP
ClientEditProt->setText(QString::number(LocalTcpClientSocket->localPort()));
ClientEditIP->setText(LocalTcpClientSocket->localAddress().toString());
ui->verticalLayout_9->insertLayout(1,ClientLayout);
ClientEditProt->show();
ClientEditIP->show();
ClientShowLocalProtLabel->show();
ClientShowLocalIptLabel->show();
//当连接上服务器之后设置控件不可用
ui->comboBox_ipaddress->setEnabled(false);
ui->comboBox_protocol->setEnabled(false);
ui->lineEdit_prot->setEnabled(false);
ui->pushButton_connect->setText("断开连接");
}
//客户端模式:断开服务器
void Widget::LocalTcpClientDisconnectedSlot()
{
ui->verticalLayout_9->removeWidget(ClientEditProt);
ui->verticalLayout_9->removeWidget(ClientEditIP);
ui->verticalLayout_9->removeWidget(ClientShowLocalProtLabel);
ui->verticalLayout_9->removeWidget(ClientShowLocalIptLabel);
ui->verticalLayout_9->removeItem(ClientLayout);
ClientEditProt->close();
ClientEditIP->close();
ClientShowLocalProtLabel->close();
ClientShowLocalIptLabel->close();
ui->pushButton_connect->setText("连接");
//当断开上服务器之后设置控件可用
ui->comboBox_ipaddress->setEnabled(true);
ui->comboBox_protocol->setEnabled(true);
ui->lineEdit_prot->setEnabled(true);
}
//客户端模式:读取服务器发过来的数据
void Widget::LocalTcpClientReadDtatSlot()
{
//移动滚动条到底部
QScrollBar *scrollbar = ui->plainTextEdit_ShowData->verticalScrollBar();
if(scrollbar)
{
scrollbar->setSliderPosition(scrollbar->maximum());
}
/*判断显示的数据长度是否超出*/
QString text=ui->plainTextEdit_ShowData->toPlainText();
if(text.length()>1000) ui->plainTextEdit_ShowData->setPlainText(""); //清空显示
QByteArray array=LocalTcpClientSocket->readAll();
//记录接收的字节数并显示
TxCount+=QString(array).toLocal8Bit().length();
ui->lcdNumber_RxNumber->display(TxCount);
text="";
//判断是否需要显示时间
if(ui->checkBox_ShowTime->isChecked())
{
QDateTime time = QDateTime::currentDateTime(); //获取系统现在的时间
text+= time.toString("yyyy-MM-dd hh:mm:ss ddd"); //设置显示格式
text+=" :";
}
text+=QString("").fromLocal8Bit(array);
ui->plainTextEdit_ShowData->appendPlainText(text);
}
void Widget::on_comboBox_protocol_activated(int index)
{
switch(index)
{
case 0: //服务器模式
ui->label_ip->setText("2.本地IP地址");
ui->label_prot->setText("3.本地端口号");
ui->comboBox_ipaddress->clear();
ui->comboBox_ipaddress->addItem("QHostAddress::Any");
break;
case 1: //客户端模式
ui->label_ip->setText("2.服务器IP地址");
ui->label_prot->setText("3.服务器端口号");
ui->comboBox_ipaddress->clear();
break;
}
QList<QHostAddress> list = QNetworkInterface::allAddresses();
for(int i=0;i<list.count();i++)
{
QHostAddress addr=list.at(i);
if(addr.protocol() == QAbstractSocket::IPv4Protocol)
{
ui->comboBox_ipaddress->addItem(addr.toString());
}
}
}
//发送数据
void Widget::on_pushButton_SendData_clicked()
{
QString text=ui->lineEdit_InputTxDtat->text();
if(text.isEmpty())
{
QMessageBox::warning(this,"发送错误","发送的数据不能为空!",QMessageBox::Ok);
return;
}
if(ui->checkBox_TxBit->isChecked()) //发送附加位
{
text+="\r\n";
}
QByteArray array=text.toLocal8Bit();
int count=0;
switch(ui->comboBox_protocol->currentIndex())
{
case 0: //服务器模式
if(TcpFarClientList.count()<=0)
{
timer->stop(); //停止定时器
ui->checkBox_LoopTx->setChecked(false); //取消循环按钮选择
QMessageBox::warning(this,"发送错误","没有连接的客户端!",QMessageBox::Ok);
return;
}
for(int i=0;i<TcpFarClientList.count();i++)
{
//取出地址列表中的一个客户端地址
QTcpSocket *item = TcpFarClientList.at(i);
count=item->write(array);
}
TxCount+=count;
break;
case 1: //客户端模式
if(LocalTcpClientSocket->state()==QAbstractSocket::ConnectedState)
{
TxCount+=LocalTcpClientSocket->write(array);
}
else
{
LocalTcpClientSocket->close();
timer->stop(); //停止定时器
ui->checkBox_LoopTx->setChecked(false); //取消循环按钮选择
QMessageBox::warning(this,"发送错误","未连接服务器!",QMessageBox::Ok);
return;
}
break;
}
ui->lcdNumber_TxNumber->display(TxCount);
}
//清除计数
void Widget::on_pushButton_clear_clicked()
{
TxCount=0;
RxCount=0;
ui->lcdNumber_RxNumber->display(0);
ui->lcdNumber_TxNumber->display(0);
}
//服务器模式:响应新连接的客户端
void Widget::NewTcpConnection()
{
/*创建本地服务器套接字*/
QTcpSocket *ServerSocket=LocalTcpServer->nextPendingConnection();
/*关联可读信号*/
connect(ServerSocket,SIGNAL(readyRead()),this,SLOT(ReadTcpClientData()));
/*关联断开信号*/
connect(ServerSocket,SIGNAL(disconnected()),this,SLOT(TcpClientDisconnected()));
TcpFarClientList.append(ServerSocket);//添加到列表
//显示已经连接的客户端
ClientComboBoxList->clear();
for(int i=0;i<TcpFarClientList.count();i++)
{
QString info=TcpFarClientList.at(i)->peerAddress().toString();
info+=":";
info+=QString::number(TcpFarClientList.at(i)->peerPort());
ClientComboBoxList->addItem(info);
}
}
//服务器模式:响应断开的客户端
void Widget::TcpClientDisconnected()
{
for(int i=0;i<TcpFarClientList.count();i++)
{
//取出地址列表中的一个客户端地址
QTcpSocket *item = TcpFarClientList.at(i);
//判断该客户端是否已经断开
if(item->socketDescriptor()==-1)
{
TcpFarClientList.removeAt(i);
}
}
//显示已经连接的客户端
ClientComboBoxList->clear();
for(int i=0;i<TcpFarClientList.count();i++)
{
QString info=TcpFarClientList.at(i)->peerAddress().toString();
info+=":";
info+=QString::number(TcpFarClientList.at(i)->peerPort());
ClientComboBoxList->addItem(info);
}
}
//服务器模式:读数据
void Widget::ReadTcpClientData()
{
/*移动滚动条到底部*/
QScrollBar *scrollbar = ui->plainTextEdit_ShowData->verticalScrollBar();
if(scrollbar)
{
scrollbar->setSliderPosition(scrollbar->maximum());
}
//设置光标到文本末尾
ui->plainTextEdit_ShowData->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
for(int i=0;i<TcpFarClientList.count();i++)
{
if(!TcpFarClientList.at(i)->atEnd())
{
QByteArray array=TcpFarClientList.at(i)->readAll();;
//记录接收的字节数并显示
RxCount+=QString(array).toLocal8Bit().length();
ui->lcdNumber_RxNumber->display(RxCount);
QString text;
//判断是否需要显示时间
if(ui->checkBox_ShowTime->isChecked())
{
QDateTime time = QDateTime::currentDateTime(); //获取系统现在的时间
text+= time.toString("【yyyy-MM-dd hh:mm:ss ddd"); //设置显示格式
text+="】:";
}
text+=QString("").fromLocal8Bit(array);
ui->plainTextEdit_ShowData->appendPlainText(text);
}
}
}
//关于
void Widget::on_About_clicked()
{
QMessageBox::information(this,tr("帮助提示"),"本软件用于TCP网络协议调试!\n"
"暂不支持UDP协议调试!\n"
"如果第一次打开软件字体显示不全\n"
"需要关闭应用第二次打开即可自动适应\n"
"软件作者:DS小龙哥\n"
"BUG反馈:1126626497@qq.com");
}
//是否开始循环发送数据
void Widget::on_checkBox_LoopTx_clicked()
{
if(ui->checkBox_LoopTx->isChecked()) //是否选择复选框
{
int cnt=ui->lineEdi_LoopTime->text().toInt();
if(cnt<=0)
{
QMessageBox::warning(this,"错误提示","发送的时间不合法!",QMessageBox::Ok);
ui->checkBox_LoopTx->setChecked(false);
return;
}
timer->start(cnt);
}
else
{
timer->stop(); //停止定时器
}
}
//定时发送
void Widget::update(void)
{
on_pushButton_SendData_clicked();
}
void Widget::on_pushButton_cleanShow_clicked()
{
ui->plainTextEdit_ShowData->setPlainText(""); //清除数据
}
3.2 wigdet.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QHostInfo> //获取计算机网络信息
#include <QUdpSocket>
#include <QtNetwork>
#include <QHostInfo>
#include <QDebug>
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
#include <QMessageBox>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QComboBox>
#include <QFile>
#include <QTimer>
#include <QScrollBar>
#include <QScrollBar>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
int TxCount;
int RxCount;
//关于客户端模式相关的变量定义
QTcpServer *TcpServer;
QTcpSocket *ServerSocket;
QTcpSocket *LocalTcpClientSocket;
QLineEdit *ClientEditProt;
QLineEdit *ClientEditIP;
QLabel *ClientShowLocalProtLabel;
QLabel *ClientShowLocalIptLabel;
QHBoxLayout *ClientLayout;
void comboBox_config();
void NewClinet();
//关于服务器相关的变量定义
QTcpServer *LocalTcpServer;
void NewServer();
QList<QTcpSocket*> TcpFarClientList;
QLabel *SaverShowLocalProtLabel;
QComboBox *ClientComboBoxList;
QHBoxLayout *ServerLayout;
void SetStyle(const QString &qssFile);
QTimer *timer;
private slots:
void on_pushButton_connect_clicked();
void LocalTcpClientConnectedSlot();
void LocalTcpClientDisconnectedSlot();
void LocalTcpClientReadDtatSlot();
void NewTcpConnection();
void TcpClientDisconnected();
void ReadTcpClientData();
void on_comboBox_protocol_activated(int index);
void on_pushButton_SendData_clicked();
void on_pushButton_clear_clicked();
void on_About_clicked();
void on_checkBox_LoopTx_clicked();
void update();
void on_pushButton_cleanShow_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
3.3 UI设计界面