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

简介

  • 软件开发中,可能经常会用到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() {
      	//处理断开连接请求
      }
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【操作系统】1.1 操作系统的基础概念、功能和目标以及特性

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

手机开机入网流程 KPI接通率和掉线率

今天我们来学习手机开机入网流程是怎么样的。以及RRC连接和重建流程(和博主之前讲TCP三次握手&#xff0c;四次挥手原理很相似)是什么样的&#xff0c;还有天线的KPI指标都包括什么&#xff0c;是不是很期待啊~ 目录 手机开机入网流程 ATTACH/RRC连接建立过程 KPI接通率和掉…

MongoDB基础知识~

引入MongoDB&#xff1a; 在面对高并发&#xff0c;高效率存储和访问&#xff0c;高扩展性和高可用性等的需求下&#xff0c;我们之前所学习过的关系型数据库(MySql,sql server…)显得有点力不从心&#xff0c;而这些需求在我们的生活中也是随处可见的&#xff0c;例如在社交中…

node插件express(路由)的插件使用(二)——cookie 和 session的基本使用区别

文章目录 前言一、express 框架中的 cookie0、cookie的介绍和作用1. 设置cookie2.删除cookie3.获取cookie&#xff08;1&#xff09;安装cookie-parser&#xff08;2&#xff09;导入cookie-parser&#xff08;3&#xff09;注册中间件&#xff08;4&#xff09;获取cookie&…

力扣刷题篇之栈与队列2(待修改)

系列文章目录 目录 系列文章目录 前言 一、最小/大栈 二、字符串去重问题 三、栈与括号匹配 总结 前言 本系列是个人力扣刷题汇总&#xff0c;本文是栈与队列。刷题顺序按照[力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 - 力扣&#xff08;LeetCode&#xff09…

Nginx:Windows详细安装部署教程

一、Nginx简介 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的。 它也是一种轻量级的Web服务器…

解决springboot接受buffer文件为null(从picgo上传buffer看springmvc处理过程)

1. 前言&#xff1a; picgo插件的简单开发 上篇文章我们简单写了picgo上传插件&#xff0c;但是当我们测试的时候&#xff0c;发现问题了&#xff0c;后端MultipartFile file接受到的文件为null。 2. 排查问题&#xff1a; 参考的文档 picgo api列表关于multipart form-data中…

C语言从入门到精通之【概述】

#include指令和头文件 例如#include <stdio.h>&#xff0c;我们经常看到C文件最上面会有类似这样的语句&#xff0c;它的作用相当于把stdio.h文件中的所有内容都输入该行所在的位置。实际上&#xff0c;这是一种“拷贝-粘贴”的操作。 #include这行代码是一条C预处理器…

LeetCode200.岛屿数量

看完题目我还感觉这道题目有点难&#xff0c;没想到20分钟不到就完全靠自己给写出来了。我就是按照自己的想法来&#xff0c;我用一个等大的visit数组来表示grid数组中的这个元素是否被访问过&#xff08;是否已经被判断了是不是岛屿&#xff09;。 先用一个大的循环对grid数组…

按键精灵中的字符串常用的场景

在使用按键精灵编写脚本时&#xff0c;与字符串有关的场景有以下几种&#xff1a; 1. 用时间字符串记录脚本使用截止使用时间 Dim localTime "2023-11-12 00:15:14" Dim networkTime GetNetworkTime() TracePrint networkTime If networkTime > localTime The…

KT6368A蓝牙芯片的出现部分芯片距离短换芯片就好是什么问题呢

一、简介 KT6368A蓝牙芯片的出现部分芯片距离短&#xff0c;换一个芯片距离就好了&#xff0c;是什么问题呢&#xff1f;生产2K的样子 详细说明 按照我们出货客户的跟踪情况&#xff0c;这种问题&#xff0c;可能性极低因为芯片本身的不良率&#xff0c;目前是控制在千分之三…

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

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

【C++】手写堆

手写堆&#xff08;小顶堆&#xff09; 堆使用数组存储&#xff0c;下标从1开始&#xff08;下标从0开始也可以&#xff09;。 下标为u的节点&#xff1a; 左子节点下标为&#xff1a;2 * u&#xff08;下标从0开始&#xff0c;左子节点则为2 * i 1&#xff09;右子节点下标…

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

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

NGINX三种虚拟主机的配置

基于IP的配置 首先在原本基础上增加两个IP地址 [rootlocalhost conf.d]# nmcli connection modify ens33 ipv4.addresses 192.168.38.140 [rootlocalhost conf.d]# nmcli connection modify ens33 ipv4.addresses 192.168.38.150 [rootlocalhost conf.d]# nmcli connection u…

绝了!现在制作电子期刊这么快而有效了?

​随着科技的进步&#xff0c;制作电子期刊已经变得越来越简单和高效。现在&#xff0c;您只需要一台电脑或手机&#xff0c;就可以快速制作出精美的电子期刊&#xff0c;而且还能有效地吸引读者的注意力。 但是如何快而有效的制作电子期刊呢&#xff1f; 1.首先打开FLBOOK在线…

网络安全之认识托管威胁检测与响应(MDR)

随着数字化转型加速&#xff0c;企业的IT环境日益复杂&#xff0c;面临的网络安全威胁也在不断增加。传统的防御措施已经无法有效应对新型威胁&#xff0c;而且很多企业缺乏专业的网络安全团队和技术手段&#xff0c;导致大量的安全事件未能及时被发现和处理。 在这种背景下&a…

Java --- 直接内存

一、直接内存 1、不是虚拟机运行时数据区的一部分&#xff0c;也不是《Java虚拟机规范》中定义的内存区域。 2、直接内存是在Java堆外的&#xff0c;直接向系统申请的内存区间。 3、来源于NIO&#xff0c;通过存在堆中的DirectByteBuffer操作Native内存。 4、访问直接内存的…

贝锐蒲公英X1解决远程访问NAS难题

由于经常在外出差和旅游&#xff0c;需要实现即使在外地也能远程登录回去家里的NAS去处理事情或传输文件&#xff0c;因此解决方案之一是搭建一个安全简易的个人私有云。 实施难度 &#xff08;1&#xff09;家庭网络无公网IP&#xff0c;且公网IP价格昂贵&#xff08;2&…

伙伴(buddy)系统原理

一、伙伴算法的由来 在实际情况中&#xff0c;操作系统必须能够在任意时刻申请和释放任意大小的内存&#xff0c;该函数的实现需要考虑延时问题和碎片问题。 延时问题指的是系统查找到可分配单元的时间变长&#xff0c;例如程序请求分配一个64KB的内存空间&#xff0c;系统查看…