基于多客户端 TCP 的 Qt 网络通信

此文章只实现简单的多客户的TCP 的 Qt 网络通信,仅供参考。

单客户端TCP通信请参考
基于 TCP 的 Qt 网络通信
使用线程池实现服务端同时处理多个客户端操作,每当有一个客户端连接到服务端,则服务端创建一个子线程与其客户端通信,以此实现实现处理多个客户端。当客户端断开连接时,及关闭对应的通信套接字,并释放对应子线程资源;
在 Qt 中使用线程池需要先创建任务,添加到线程池中的每一个任务都需要是一个 QRunnable 类型,因此在程序中需要创建子类继承 QRunnable 这个类,然后重写 run() 方法,在这个函数中编写要在线程池中执行的任务,并将这个子类对象传递给线程池,这样任务就可以被线程池中的某个工作的线程处理掉了。

1. QTcpServer

1.1 通信流程

创建套接字服务器 QTcpServer 对象
通过 QTcpServer 对象设置监听,即:QTcpServer::listen()
基于 QTcpServer::newConnection() 信号检测是否有新的客户端连接
如果有新的客户端连接:
1)判断是否有未使用的通信队列;
2)将得到的通信套接字赋值给一个未使用的通信套接字;
3)将当前通信套接字加入到线程池中;
再子线程中使用套接字对象 QTcpSocket 和客户端进行通信
断开连接时释放队列中对应的通信套接字;

1.2 代码片段

服务器端的窗口界面如下图所示:
请添加图片描述

runnable.h

typedef struct _SOCKETINFO
{
    int index;
    int fd;
    QTcpSocket* socket;
    _SOCKETINFO(){
        index = -1;
        fd = 0;
        socket = nullptr;
    }
}SOCKETINFO;

class Runnable : public QObject,public QRunnable
{
    Q_OBJECT
public:
    explicit Runnable(SOCKETINFO socket,QObject *parent = nullptr);

    void run() override;

private slots:
    void slotDisconnected();

signals:
    void sigDisconnected(int index);

private:
    SOCKETINFO     m_socket;

};

runnable.cpp

#include "runnable.h"

Runnable::Runnable(SOCKETINFO socket, QObject *parent) : m_socket(socket), QObject(parent)
{
    this->setAutoDelete(false);
}

void Runnable::run()
{
    // 检测是否有客户端数据
    connect(m_socket.socket, &QTcpSocket::readyRead, this, [=]()
    {
        // 接收数据
        QString recvMsg = m_socket.socket->readAll();
        m_socket.socket->write(recvMsg.toUtf8());
    });
    // 客户端断开了连接
    connect(m_socket.socket, &QTcpSocket::disconnected, this, &Runnable::slotDisconnected);
}

void Runnable::slotDisconnected()
{
    // 客户端断开了连接
    emit sigDisconnected(m_socket.index);
    this->deleteLater();
}

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void nextPendingConnection();

    void slotDisconnected(int index);

private:
    Ui::MainWindow *ui;
    QTcpServer* m_server;
    SOCKETINFO     m_tcpConn[128];
};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle(QStringLiteral("TCP - 服务器"));
    // 设置 QThreadPool 线程池最大线程个数
    QThreadPool::globalInstance()->setMaxThreadCount(10);
    // 创建 QTcpServer 对象
    m_server = new QTcpServer(this);
    // 检测是否有新的客户端连接
    connect(m_server, &QTcpServer::newConnection, this, &MainWindow::nextPendingConnection);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    unsigned short port = ui->lineEdit->text().toInt();
    // 设置服务器监听
    m_server->listen(QHostAddress::Any, port);
    ui->pushButton->setEnabled(false);
}

void MainWindow::nextPendingConnection()
{
    for(int i=0;i<128;i++)
    {
        if(m_tcpConn[i].fd == 0)
        {
            m_tcpConn[i].index = i;
            m_tcpConn[i].fd = 1;
            m_tcpConn[i].socket = m_server->nextPendingConnection();
            ui->textBrowser->append(QStringLiteral("成功和客户端建立了新的连接..."));
            Runnable *run = new Runnable(m_tcpConn[i]);
            connect(run,&Runnable::sigDisconnected,this,&MainWindow::slotDisconnected);
            QThreadPool::globalInstance()->start(run);
            break;
        }
    }
}

void MainWindow::slotDisconnected(int index)
{
    ui->textBrowser->append(QStringLiteral("客户端断开连接..."));
    m_tcpConn[index].index = -1;
    m_tcpConn[index].fd = 0;
    m_tcpConn[index].socket->deleteLater();
    m_tcpConn[index].socket = nullptr;
}

2 客户端

客户端代码请参照基于 TCP 的 Qt 网络通信中的客户端代码;

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
TCP多线程客户端封装是一种将TCP协议与多线程技术相结合的方式,用来实现在Qt框架下进行网络通信的封装工具。Qt是一种跨平台的应用程序开发框架,提供了丰富的功能和工具,而TCP协议则是一种用于在互联网上进行数据传输的协议。 TCP多线程客户端封装的实现思路如下: 首先,需要在Qt项目中引入相应的网络库,以便能够使用TCP协议进行通信。可以使用Qt的Network模块,其中包含了一系列用于网络通信的类和函数。 接下来,可以创建一个自定义的TCP客户端类,该类继承自QtQThread类,以实现多线程功能。在该类中,可以定义一些成员变量,如用于保存服务器IP地址和端口号的变量,以及用于与服务器进行通信的套接字变量。 然后,在自定义的TCP客户端类中,可以重写QThread的run()函数,将具体的TCP通信逻辑放在其中。可以使用Qt提供的QTcpSocket类来建立与服务器的连接,并通过该套接字与服务器进行数据的发送和接收。 最后,在Qt应用程序中,可以创建一个实例化的TCP客户端对象,并调用其 start() 函数来启动多线程。通过该客户端对象的成员函数,可以与服务器进行通信,发送数据并接收来自服务器的响应。 总结:TCP多线程客户端封装是一种基于Qt框架和TCP协议的封装工具,可以轻松实现在Qt应用程序中进行网络通信的功能。通过多线程的方式,可以保证网络通信与界面操作的并行进行,提高了程序的性能和响应速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值