如何在 Qt 中使用多线程构建高效的 TCP 服务器(C++)

一、前言

在网络编程中,处理大量并发连接是一项挑战。为了提高服务器的性能,特别是在高并发场景下,使用多线程来处理客户端连接是一种常见的策略。本篇文章将介绍如何使用 Qt 框架,在 C++ 中实现一个支持多线程的高并发服务器。

为什么需要重写 incomingConnection()

1.incomingConnection() 是处理新客户端连接的入口点。当有新连接时,Qt 会调用该方法并传递一个 socketDescriptor(套接字描述符)。默认情况下,QTcpServer 并不会自动为每个连接创建和处理新的 QTcpSocket 实例。重写 incomingConnection() 允许我们自定义如何处理新连接,包括为每个连接创建新的 QTcpSocket 或自定义的处理类(如 ClientHandler)。

2.在高并发场景下,为了防止单线程阻塞导致性能问题,需要将每个客户端的处理逻辑放到一个单独的线程中。通过重写 incomingConnection(),我们可以在接受到新的客户端连接时,为其创建一个新的线程并在其中处理客户端的请求。

3.通过重写 incomingConnection(),可以更好地管理客户端连接的生命周期。

二、项目结构

  • ClientHandler:用于处理每个客户端连接的类。
  • TCPServer:继承自 QTcpServer,用于管理客户端连接的服务器类。
  • QtEthernetServer:提供服务器初始化及启动的接口。

三、代码实现

1. ClientHandler

ClientHandler 类负责处理单个客户端的连接,包括读取数据和处理客户端断开连接的情况。

class ClientHandler : public QObject 
{
    Q_OBJECT

public:
// ClientHandler(qintptr socketDescriptor, QObject* parent = nullptr);
    void init(qintptr _socketDescriptor);
    int conState()
    {
        if (socket->state() == QAbstractSocket::ConnectedState)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
public slots:
    void handleClient();
    void onReadyRead();
    void onDisconnected();
private:
    QTcpSocket* socket;
    qintptr socketDescriptor;
};
void ClientHandler::init(qintptr _socketDescriptor)
{
    socketDescriptor = _socketDescriptor;
}

void ClientHandler::handleClient() {
    socket = new QTcpSocket;
   
    if (socket->setSocketDescriptor(socketDescriptor)) 
    {
        connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onReadyRead);
        connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
    }
    else {
        delete socket;
        socket = nullptr;
        emit destroyed();
    }
  
}

void ClientHandler::onReadyRead()
{
    /*读取数据*/
}
void ClientHandler::onDisconnected() {
    // 处理客户端断开连接的逻辑
}

2. TCPServer

TCPServer 类继承自 QTcpServer,负责监听并接受新的客户端连接。每当有新的客户端连接时,TCPServer 会为其创建一个 ClientHandler 实例,并将其分配到一个新线程中处理。

class TCPServer : public QTcpServer
{
public:
    ClientHandler* handler;
protected:
    void incomingConnection(qintptr socketDescriptor) override;
};
void TCPServer::incomingConnection(qintptr socketDescriptor)
{
    QThread* thread = new QThread;
    handler = new ClientHandler();
    handler->init(socketDescriptor);
    handler->moveToThread(thread);
    connect(thread, &QThread::started, handler, &ClientHandler::handleClient);
    connect(handler, &ClientHandler::destroyed, thread, &QThread::quit);
    connect(thread, &QThread::finished, thread, &QThread::deleteLater);
    thread->start();
}

3. QtEthernetServer

QtEthernetServer 提供了服务器的初始化和启动方法。

void QtEthernetServer::init(QString strIp, int Port)
{
    server = new TCPServer;
    server->init();
    server->setEthernetServer(q);
    if (!server->listen(QHostAddress::Any, Port))
    {
        OiWarning() << "开启服务器失败...";
    }
    else 
    {
        OiWarning() << "开启服务器...";
    }
        q->connect(server, SIGNAL(newConnection()), SLOT(onConnected()));
    }
}
void QtEthernetServer::onConnected()
{
    while (server->hasPendingConnections())
    {
        d->server->nextPendingConnection();
        OiWarning() << "已经连接服务器...";
    }
}
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt是一个跨平台的C++应用程序开发框架,其包含了用于网络编程的模块,可以轻松地实现TCP服务器多线程。 在Qt,我们可以使用QTcpServer类来实现一个TCP服务器。通过该类,我们可以监听指定的IP地址和端口,接收客户端的连接请求,并对连接进行处理。为了实现多线程,我们可以通过创建一个新的线程来处理每个连接。这样可以使服务器能够同时处理多个客户端的请求,提高服务器的并发性能。 具体实现步骤如下: 1. 首先,创建一个继承自QObject的类,作为我们的服务器类。在该类,声明一个QTcpServer对象用于监听客户端连接,以及一个QList<QThread*>对象用于保存所有处理连接的线程。 2. 在服务器类的构造函数,实例化QTcpServer对象,并通过调用listen函数来开始监听指定的IP地址和端口。 3. 定义一个槽函数,用于处理新的连接。在该槽函数,可以通过调用QTcpServer的nextPendingConnection函数来获取新的连接。然后,创建一个新的线程,并将连接传递给该线程进行处理。 4. 在线程类,重写run函数。在run函数,可以处理连接的具体业务逻辑。当连接处理完毕后,可以通过调用disconnectFromHost函数来断开连接,并结束线程的执行。 5. 在服务器类的析构函数,需要遍历所有线程对象,并调用wait函数等待线程的结束。然后,删除所有线程对象,释放资源。 通过以上步骤,我们就可以实现一个Qt TCP服务器多线程。这样的服务器可以同时处理多个客户端的请求,提高了服务器的并发性能。同时,Qt的跨平台特性保证了服务器在不同操作系统上的兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值