当前位置: 首页 > news >正文

手动开发一个TCP服务器调试工具(四):构建完整的UI与功能联合的TCP服务器应用

在现代应用中,TCP服务器通常用于实现可靠的数据传输,而在需要用户交互的场景下,结合图形用户界面(UI)进行操作会大大提升用户体验。本文将结合一个使用Qt与C++构建的TCP服务器应用,介绍如何将UI和TCP服务器的功能有效结合,实现一个完整的功能应用。

1. 系统设计概述

我们设计的TCP服务器应用主要由两个部分组成:

  • TCP服务器模块(TcpServer):负责客户端的连接管理、消息的发送与接收。
  • UI模块(MainWindow):通过Qt提供的图形界面,展示服务器的状态信息、客户端列表,并允许用户进行数据发送和操作。

在这个设计中,TCP服务器负责处理底层的连接、数据传输以及错误和警告的管理,而UI则为用户提供了简便的操作界面。

源码下载

通过网盘分享的文件:完整的UI与功能联合的TCP服务器应用
链接: https://pan.baidu.com/s/1aWIAPyW7q4dMZVcnhzfD0A?pwd=jkcf 提取码: jkcf

2. TCP服务器模块

2.1 TCP服务器类设计(TcpServer)

TcpServer类是服务器的核心,继承自QThread,利用线程独立运行以避免阻塞主UI线程。以下是主要功能实现:

启动与关闭服务器
bool TcpServer::startServer(int port)
{if(!tcpServer){tcpServer = new QTcpServer();connect(tcpServer, &QTcpServer::newConnection, this, &TcpServer::onNewConnection);}if (!tcpServer->listen(QHostAddress::Any, static_cast<quint16>(port))){emit errors(1, tc("服务器启动失败:%1 端口: ").arg(tcpServer->errorString()) + QString::number(port));return false;}emit informations(1, tc("服务器启动成功,监听端口: ") + QString::number(port));return true;
}
  • startServer(int port):启动服务器并监听指定端口。如果服务器启动失败,会通过emit发送错误信号。
  • closeServer():关闭服务器并断开所有客户端的连接。
客户端连接管理

当有新客户端连接时,onNewConnection()方法会被触发,建立与客户端的连接并保存到clients列表中。

void TcpServer::onNewConnection()
{QTcpSocket *clientSocket = tcpServer->nextPendingConnection();qintptr socketDescriptor = clientSocket->socketDescriptor();clients.insert(socketDescriptor, clientSocket);  // 将客户端添加到列表中connect(clientSocket, &QTcpSocket::disconnected, this, &TcpServer::onClientDisconnected);connect(clientSocket, &QTcpSocket::readyRead, this, &TcpServer::onReadyRead);emit clientConnected(socketDescriptor);  // 触发客户端连接信号
}
  • 每当有客户端连接时,客户端的socketDescriptor和对应的QTcpSocket实例会被保存到clients映射表中。
数据接收与发送

onReadyRead()用于接收客户端发送的数据,而sendToClient()则用于向客户端发送消息。

void TcpServer::onReadyRead()
{QTcpSocket *clientSocket = qobject_cast<QTcpSocket*>(sender());if (clientSocket) {QByteArray data = clientSocket->readAll();emit ClientInfor(clientSocket->socketDescriptor(), data, true);  // 触发数据接收信号}
}void TcpServer::sendToClient(qintptr socketDescriptor, const QByteArray &message)
{QTcpSocket *clientSocket = clients.value(socketDescriptor, nullptr);if (clientSocket){clientSocket->write(message);emit ClientInfor(clientSocket->socketDescriptor(), message, false);  // 触发数据发送信号} else {emit errors(2, tc("无法找到指定的客户端,描述符: ") + QString::number(socketDescriptor));}
}
  • 当接收到数据时,onReadyRead()读取客户端的数据并通过信号ClientInfor通知UI。
  • sendToClient()会将消息写入指定的客户端连接中。

3. UI设计与实现

3.1 主窗口(MainWindow)设计

MainWindow类是应用的UI核心,使用Qt的QWidget及各种控件(如按钮、文本框等)构建了直观的操作界面。UI主要功能包括:

启动与关闭服务器

通过点击按钮来启动和关闭TCP服务器。点击启动时,会触发on_startServerButton_clicked()方法,验证端口号并调用startServer()启动服务器。

void MainWindow::on_startServerButton_clicked()
{int port = ui->portspinBox->value();if (port > 0) {if (server->startServer(port)) {writeRunTimeMsgs(QString("服务器成功启动,监听端口:") + QString::number(port), 2);ui->startServerButton->setEnabled(false);  // 禁用启动按钮} else {writeRunTimeMsgs(QString("服务器启动失败!"), 0);}} else {writeRunTimeMsgs(QString("无效的端口号!"), 1);}
}
  • 如果服务器成功启动,UI会显示成功信息,并禁用启动按钮。
客户端连接显示

通过onClientConnected()onClientDisconnected(),分别处理客户端连接和断开连接事件,并将客户端的描述符显示在UI列表中。

void MainWindow::onClientConnected(qintptr socketDescriptor)
{writeRunTimeMsgs(QString("客户端连接,描述符: ") + QString::number(socketDescriptor), 2);QStandardItem *item = new QStandardItem(QString("客户端#%1").arg(socketDescriptor));item->setData(socketDescriptor, Qt::UserRole);model->appendRow(item);  // 将客户端信息添加到客户端列表
}
数据发送

MainWindow通过TimeSendWidget组件来创建数据发送框,允许用户选择客户端并输入数据发送。

void MainWindow::createSendLinEdit()
{for (int i = 0; i < 5; i++) {TimeSendWidget *sendWidget = new TimeSendWidget;sendWidget->setComBoxModel(model);  // 设置客户端列表connect(sendWidget, &TimeSendWidget::sendLineData, [=](const qintptr socketDescriptor, const QByteArray &data) {if (data.isEmpty()) {writeRunTimeMsgs(QString("信息为空,拒绝发送"), Warning);return;}((socketDescriptor < 0) ? server->sendToAllClients(data) : server->sendToClient(socketDescriptor, data));});ui->verticalLayout->addWidget(sendWidget);  // 将发送框添加到UI布局中}
}
  • 用户可以选择客户端并输入数据,点击发送按钮时,数据将通过sendToClient()sendToAllClients()发送。

3.2 消息显示

UI通过QTextEdit显示运行时消息以及接收到的数据:

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 = QString("【错误】");color = "red";break;case 1: // 警告prefix = QString("【警告】");color = "orange";break;case 2: // 信息prefix = QString("【信息】");color = "#00ff00";break;}// 将消息插入到QTextEdit中并改变颜色QString formattedMsg = QString("<span style='color:%1;'>%2 %3: %4</span>").arg(color, prefix, timestamp, msg);ui->outputTextEdit->append(formattedMsg);
}
  • 根据不同级别的消息(错误、警告、信息),UI会显示不同颜色的提示信息。

4. 总结

本应用通过Qt与C++结合,构建了一个完整的TCP服务器应用,既提供了功能强大的服务器端数据管理,又通过直观的UI设计,便于用户操作。服务器支持多客户端连接、群发与单独发送数据,并能实时处理错误和信息,确保了应用的高效和稳定运行。通过本系统,用户可以轻松管理连接的客户端,进行数据交互,且在服务器端出现任何问题时可以即时反馈。

http://www.dtcms.com/a/320971.html

相关文章:

  • 脚本统计MongoDB集合结构信息
  • 从0开始的中后台管理系统-5(userList动态展示以及上传图片和弹出创建用户表单)
  • 【MongoDB学习笔记1】MongoDB的常用命令介绍-数据库操作、集合操作、文档操作、文档分页查询、高级查询
  • 操作系统: 线程(Thread)
  • Lazada东南亚矩阵营销破局:指纹手机如何以“批量智控+数据中枢”重构运营生态
  • Android 之 OOM的产生和解决办法
  • Android 之 ANR问题的全面解析与优化方案
  • 综合项目记录:自动化备份全网服务器数据平台
  • 日本站群服务器与普通日本服务器对比
  • 深入解析C++流运算符(>>和<<)重载:为何必须使用全局函数与友元机制
  • [论文阅读] 人工智能 + 软件工程 | LLM协作新突破:用多智能体强化学习实现高效协同——解析MAGRPO算法
  • 在发布应用程序内测时如何选择合适的分发上架方式?
  • Vite 深度解析:现代前端开发引擎
  • 瑞利杂波背景下不同环境的虚警概率与目标检测概率仿真
  • C# 异步编程(GUI程序中的异步操作)
  • 日常开发-5,工具使用。datagrip mysql 写查询语句 数据库表名和字段 无法提示
  • 语音识别 SenseVoice与FunASR对比
  • 机器学习——07 朴素贝叶斯
  • 数据结构(二叉树)
  • C++ 模拟实现 map 和 set:掌握核心数据结构
  • Jmeter接口测试实例
  • Idea配置——build system的选项区别
  • 经常问的14002
  • 5.0.9 C# wpf通过WindowsFormsHost嵌入winform控件
  • hive-日期拆分为多行
  • 32-Hive SQL DML语法之查询数据
  • 系统网络端口安全扫描脚本及详解
  • SpringBoot激活指定profile的方式
  • linux统计文本文件中行数、单词数和字节数的命令行工具wc介绍
  • 深入解析Linux信号处理机制