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


    简介

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

    界面展示

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

    功能说明

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

    软件下载

    Qt实现服务端并发

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

    核心源代码

    • 这里只提供了服务端实现并发的核心源代码,主要有三个文件:

      • networkdebugtools.cpp 为主界面文件,实现UI交互。
      • tcpservertools.cpp 主要实现接受客户端连接请求,保存套接字到hash容器中。
      • tcpsockettools.cpp 中主要实现处理客户端数据和断开请求。
    • 三者之间可以自己定义信号槽实现通信,整体源代码不提供,请谅解。

    • networkdebugtools.h

    •   #ifndef NETWORKDEBUGTOOLS_H
        #define NETWORKDEBUGTOOLS_H
        
        #include 
        #include 
        #include 
        #include 
        #include "tcpservertools.h"
        #include 
        
        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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
    • networkdebugtools.cpp

    •   #include "networkdebugtools.h"
        #include "ui_networkdebugtools.h"
        #include 
        #include 
        #include 
        
        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();
        	}
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
    • tcpservertools.h

    •   #ifndef TCPSERVERTOOLS_H
        #define TCPSERVERTOOLS_H
        
        #include 
        #include 
        #include 
        #include 
        #include 
        #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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
    • 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 类型的tcpClient指针对象中
        	tcpClient->insert(socketDescriptor, socketTools);
        }
        
        
        // 设置最大连接数
        void TcpServerTools::setMaxPendingConnections(int numConnections) {
        	QTcpServer::setMaxPendingConnections(numConnections);
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
    • tcpsockettools.h

    •   #ifndef TCPSOCKETTOOLS_H
        #define TCPSOCKETTOOLS_H
        
        #include 
        
        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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • tcpsockettools.cpp

    •   #include "tcpsockettools.h"
        #include 
        
        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() {
        	//处理断开连接请求
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
  • 相关阅读:
    css让元素透明的方式
    常见的缺陷管理工具——禅道,从安装到使用手把手教会你
    GBase 8c数据库对象命名
    基于J2EE的高校毕业生就业信息管理系统
    VMware 与 SmartX 快照原理浅析与 I/O 性能对比
    小程序分包加载
    10_libpcap以及libnet
    黑马2022最新redis课程笔记知识点(面试用)
    算法通关村-----滑动窗口高频问题
    Nmap端口扫描技巧
  • 原文地址:https://blog.csdn.net/new9232/article/details/134359140