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

简介

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

界面展示

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

功能说明

  • 本程序使用Qt实现了TCP客户端和服务端。
  • 服务端支持多并发,并发数可配置。
  • 服务端支持单播和广播功能,单播模式下,可指定给某一个客户端发送请求,广播模式下,可给连接上来的所有客户端发送请求。

软件下载

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>
      
      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() {
          
          
      	//处理断开连接请求
      }
    

猜你喜欢

转载自blog.csdn.net/new9232/article/details/134359140