Qt实现TCP调试助手 - 简述如何在Qt中实现TCP多并发

news2025/1/16 20:58:03

简介

  • 软件开发中,可能经常会用到TCP调试工具。本人使用QT开发了一款TCP调试工具,方便大家使用。本文章主要介绍下,该工具的功能,以及如何在Qt中实现TCP服务器的并发。

界面展示

  • 安装界面
    在这里插入图片描述
  • 桌面图标。安装后会生成桌面图标,双击图标可以打开程序。
    在这里插入图片描述
  • 界面展示
    在这里插入图片描述

功能说明

  • 本程序使用Qt实现了TCP客户端和服务端,服务端并发数默认为100,可配置。客户端连接后,可以在服务端看到连接的客户端信息,服务端可以指定给某一个客户端发送消息。
  • 服务端不支持广播,后续版本会完善。

软件下载

  • 本程序已经制作成安装包形式,下载安装后可直接使用。
  • gitee下载
  • CSDN资源下载

Qt实现服务端并发

  • Qt实现服务端多并发时,可以实现一个类 TcpServerTools,该类需要继承于 QTcpServer,然后重写以下两个函数
  • void setMaxPendingConnections(int numConnections);
    • 该函数设置服务端最大连接数
  • void incomingConnection(qintptr socketDescriptor);
    • 当有新连接时,会触发该函数,我们需要在该函数中,将套接字保存起来。可以将套接字保存到一个Hash中 QHash<int, TcpSocketTools*>

核心源代码

  • 这里只提供了服务端实现并发的核心源代码,主要有三个文件networkdebugtools.cpp为主界面文件,实现UI交互。tcpservertools.cpp主要实现接受客户端连接请求,保存套接字到hash容器中。tcpsockettools.cpp中主要实现处理客户端数据和断开请求。

  • 三者之间可以自己定义信号槽实现通信,整体源代码不提供,请谅解。

  • networkdebugtools.h

  •   #ifndef NETWORKDEBUGTOOLS_H
      #define NETWORKDEBUGTOOLS_H
      
      #include <QWidget>
      #include <QEvent>
      #include <QMouseEvent>
      #include <QMenu>
      #include "tcpservertools.h"
      #include <map>
      
      QT_BEGIN_NAMESPACE
      namespace Ui { class NetworkDebugTools; }
      QT_END_NAMESPACE
      
      class NetworkDebugTools : public QWidget
      {
          Q_OBJECT
      
      public:
          NetworkDebugTools(QWidget *parent = nullptr);
          ~NetworkDebugTools();
      
      private slots:
          void on_pushButton_send_clicked();
          void on_pushButton_listen_clicked();
      
      private:
          Ui::NetworkDebugTools *ui;
      
      	TcpServerTools *mTcpServerTools;
      };
      #endif // NETWORKDEBUGTOOLS_H
    
  • networkdebugtools.cpp

  •   #include "networkdebugtools.h"
      #include "ui_networkdebugtools.h"
      #include <QMessageBox>
      #include <QHostInfo>
      #include <QTableWidgetItem>
      #include "comm.h"
      
      
      NetworkDebugTools::NetworkDebugTools(QWidget *parent)
          : QWidget(parent)
          , ui(new Ui::NetworkDebugTools)
      {
          ui->setupUi(this);
      
      	mTcpServerTools = new TcpServerTools();
      }
      
      void NetworkDebugTools::on_pushButton_send_clicked()
      {
      	//获取当前选中的客户端信息
      	QString curAddr = ui->tableWidget_clientInfo->item(curRow, 0)->text();
      
      	QHash<int, TcpSocketTools*>::iterator iter = mTcpServerTools->tcpClient->begin();
      	for (; iter != mTcpServerTools->tcpClient->end(); iter++) {
      		QString iterAddr = iter.value()->peerAddress().toString() + ":" + QString::number(iter.value()->peerPort());
      		if (iterAddr.compare(curAddr) == 0) {
      			//这里hash容器tcpClient中保存的value就是socket,可以直接通过socket给客户端发送数据
      			//同样可以通过该socket获取客户端的ip和端口,然后与我们点击的客户端信息比对,就可以实现对指定客户端发送消息
      			iter.value()->write(ui->plainTextEdit_send->toPlainText().toLocal8Bit());
      			break;
      		}
      	}
      }
      
      void NetworkDebugTools::on_pushButton_listen_clicked()
      {
      	if (ui->pushButton_listen->text().compare("监听") == 0) {
      		ui->pushButton_listen->setText("关闭");
      		mTcpServerTools->setMaxPendingConnections(mConfigTools->getConnCount());
      		mTcpServerTools->startListen();
      	}
      	else {
      		ui->pushButton_listen->setText("监听");
      		mTcpServerTools->closeConnect();
      	}
      }
    
  • tcpservertools.h

  •   #ifndef TCPSERVERTOOLS_H
      #define TCPSERVERTOOLS_H
      
      #include <QWidget>
      #include <QTcpServer>
      #include <QHostInfo>
      #include <QAbstractSocket>
      #include <QTcpSocket>
      #include "tcpsockettools.h"
      
      #define THREAD_MAX 20
      
      class TcpServerTools : public QTcpServer
      {
          Q_OBJECT
      public:
          explicit TcpServerTools(QTcpServer *parent = 0);
          ~TcpServerTools();
      	//开始监听
      	bool startListen();
      	//关闭连接
      	void closeConnect();
      	//设置最大连接数
      	void setMaxPendingConnections(int numConnections);
      
      protected:
      	// 有新连接到来时,该函数会被触发
      	void incomingConnection(qintptr socketDescriptor);
      private:
      	QTcpServer *mTcpServer;   //tcp服务对象
      public:
      	QHash<int, TcpSocketTools*> *tcpClient;// 该对象中保存套接字
      };
      
      #endif // TCPSERVERTOOLS_H
    
  • tcpservertools.cpp

  •   #include "tcpservertools.h"
    
      TcpServerTools::TcpServerTools(QTcpServer *parent) : QTcpServer(parent)
      {
      	tcpClient = new  QHash<int, TcpSocketTools*>;
      }
      
      TcpServerTools::~TcpServerTools()
      {
      
      }
      
      bool TcpServerTools::startListen() {
      	//监听连接
      	this->listen(QHostAddress(mIp), mPort.toInt());
      	return true;
      }
      
      void TcpServerTools::closeConnect(){
      	// 断开连接时,删除tcpClient中保存的套接字,并清除 tcpClient
      	QHash<int, TcpSocketTools*>::const_iterator iterC = tcpClient->constBegin();
      	for (; iterC != tcpClient->constEnd(); iterC++){
      		iterC.value()->deleteLater();
      	}
      	tcpClient->clear();
      	this->close();
      }
      
      void TcpServerTools::incomingConnection(qintptr socketDescriptor) {
      
      	//创建 TcpSocketTools 对象
      	TcpSocketTools *socketTools = new TcpSocketTools(socketDescriptor);	
      	QString connAddr = socketTools->peerAddress().toString() + ":" + QString::number(socketTools->peerPort());
      
      	
      	// 有新连接时,保存socket到 QHash<int, TcpSocketTools*> 类型的tcpClient指针对象中
      	tcpClient->insert(socketDescriptor, socketTools);
      }
      
      
      // 设置最大连接数
      void TcpServerTools::setMaxPendingConnections(int numConnections) {
      	QTcpServer::setMaxPendingConnections(numConnections);
      }
    
  • tcpsockettools.h

  •   #ifndef TCPSOCKETTOOLS_H
      #define TCPSOCKETTOOLS_H
      
      #include <QTcpSocket>
      
      class TcpSocketTools : public QTcpSocket
      {
          Q_OBJECT
      public:
          explicit TcpSocketTools(qintptr socketDescriptor, QTcpSocket *parent = 0);
          ~TcpSocketTools();
      public slots :
      	void onReadyRead();
      	void onDisconnected();
      private:
      	qintptr socketID;
      };
      
      #endif // TCPSOCKETTOOLS_H
    
  • tcpsockettools.cpp

  •   #include "tcpsockettools.h"
      #include <QHostAddress>
      
      TcpSocketTools::TcpSocketTools(qintptr socketDescriptor, QTcpSocket *parent) : QTcpSocket(parent),socketID(socketDescriptor)
      {
      	this->setSocketDescriptor(socketDescriptor);
      
      	connect(this, &TcpSocketTools::readyRead, this, &TcpSocketTools::onReadyRead);
      	connect(this, &TcpSocketTools::disconnected, this, &TcpSocketTools::onDisconnected);
      }
      
      TcpSocketTools::~TcpSocketTools()
      {
      
      }
      
      void TcpSocketTools::onReadyRead() {
      	//处理接受到的数据
      }	
      
      void TcpSocketTools::onDisconnected() {
      	//处理断开连接请求
      }
    

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

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

相关文章

(三)正点原子I.MX6ULL kernel6.1挂根文件系统

一、概述 移植NXP官方最新的linux kernel&#xff08;linux-imx-lf-6.1.y&#xff09; 移植方法基本参照正点原子教程 移植开发板&#xff1a;正点原子阿尔法2.1 二、添加开发板到内核 进入内核目录下&#xff0c;先修改Makefile 打开终端&#xff1a; cp arch/arm/configs/im…

fastbins_Double Free调试

我大哥给我出了一题pwn heap题&#xff0c;当时现场的时候没解出来&#xff0c;想岔了。事后感概自己还是理解的不够透彻。决定认真再次调试下。用的是2.23版本的how2heap中fastbins_dup.c。 简单用gcc编译下&#xff0c;然后带源码调试&#xff1a; 生成一个a.out的文件&#…

C++ 运算符重载(Complex复数类)

Complex复数类 Complex.h #ifndef COMPLEX_H #define COMPLEX_H#include <iostream> using namespace std;class Complex { private:double real 0; //复数的实部double imag 0; //复数的虚部 public:Complex() default; /*无参构造*/Complex(double r); …

No186.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

解决XFCE桌面VirtualBox透明背景的问题

1 背景 笔者用的是ManjaroXFCE的组合&#xff0c;但是在使用VirtualBox时&#xff0c;会出现透明背景的问题&#xff1a; 然后发现这其实和Kvantum主题有关。下面将进行设置操作&#xff0c;去修正Kvantum相关配置修复该问题。 2 操作流程 打开Kvantum Manager&#xff1a; …

No184.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…

数据挖掘:关联规则,异常检测,挖掘的标准流程,评估指标,误差,聚类,决策树

数据挖掘&#xff1a;关联规则 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sql要…

混合A Star算法

混合A Star算法就是将A*与Lattice Graph相关联。 使用栅格地图&#xff0c;保持在栅格地图的这个节点方格里都只记录一个机器人的State&#xff0c;例如图上的弯弯的线&#xff0c;进行剪枝&#xff0c;看一个节点的Cost&#xff08;时间、消耗的能量、路径的长度、终端状态惩…

​软考-高级-系统架构设计师教程(清华第2版)【第3章 信息系统基础知识(p120~159)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第3章 信息系统基础知识(p120~159)-思维导图】 课本里章节里所有蓝色字体的思维导图

无需公网IP,贝锐花生壳内网穿透远程访问NAS

群晖DSM 7.0及以上版本 1.1 安装运行花生壳套件 &#xff08;1&#xff09;通过浏览器输入群晖NAS的内网地址&#xff0c;登录进去后&#xff0c;点击【套件中心】&#xff0c;搜索【花生壳】&#xff0c;并点击【安装套件】&#xff1b; &#xff08;2&#xff09; 勾选我接…

git命令汇总

1.git是基于ssh的代码管理工具,所以在git使用之前需要配置好ssh ssh配置教程 2.先创建仓库 3. git init在目标的git目录下创建仓库 4.git add .(或者写文件名) 5.git commit -m "标记信息" 持久化 6.git remote add origin gitgit.acwing.com:yaoaolong/11_5.git初次…

异步编程工具Promise与Async/Await:解决前端开发中的嵌套回调地狱

文章目录 Promise&#xff1a;处理异步操作的基本工具Promise.all async/await&#xff1a;更简洁的异步编程方式Promise与async/await的比较结论 当谈及JavaScript中的异步编程时&#xff0c;两个非常常见且强大的工具是Promise和async/await。在本文中&#xff0c;我们将以实…

CNN入门实战:猫狗分类

前言 CNN&#xff08;Convolutional Neural Network&#xff0c;卷积神经网络&#xff09;是一种深度学习模型&#xff0c;特别适用于处理图像数据。它通过多层卷积和池化层来提取图像的特征&#xff0c;并通过全连接层进行分类或回归等任务。CNN在图像识别、目标检测、图像分割…

ubuntu下tensorrt环境配置

文章目录 一、Ubuntu18.04环境配置1.1 安装工具链和opencv1.2 安装Nvidia相关库1.2.1 安装Nvidia显卡驱动1.2.2 安装 cuda11.31.2.3 安装 cudnn8.21.2.4 下载 tensorrt8.4.2.4 二、编写CMakeLists.txt三、TensorRT系列教程 一、Ubuntu18.04环境配置 教程同样适用与ubuntu22.04…

springcloud电影购票选座网站系统源码

开发技术&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;idea springcloud springboot mybatis vue elementui 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索电影&#xff0c;轮播图&#xff0c;电影分类&#xff0c;最近上架电影&#xff08;可…

Linux 内核启动流程

目录 链接脚本vmlinux.ldsLinux 内核启动流程分析Linux 内核入口stext__mmap_switched 函数start_kernel 函数rest_init 函数init 进程 看完Linux 内核的顶层 Makefile 以后再来看 Linux 内核的大致启动流程&#xff0c;Linux 内核的启动流程要比uboot 复杂的多&#xff0c;涉及…

第六章 DNS域名解析服务器

1、DNS简介 DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网。 DNS系统使用的是网络的查询&#xff0c;那么自然需要有监听的port。DNS使用的是53端口…

思科9300交换机使用USB进行升级ISO

一、下载ISO 一、网址 Software Download - Cisco Systems 二、找到型号 四、选择XE 软件 五、进行下载 二、COPY 进 U盘 一、、请注意&#xff01;如果你的U盘不是Fat32文件格式则交换机读取不了&#xff0c;请先格式化再复制文件。 二、下载后将 bin文件复制到U盘。 1.扩展…

js删除json数据中指定元素

delete 删除数组方法&#xff1a; function removeJSONRows() {var tab {"dataRows": [{"id": 1,"name": "使用部门"},{"id": 2,"name": "车辆走行路线"},{"id": 3,"name": &quo…