0


【QT开发】TCP服务器QTcpServer类详解及实战应用

QTcpServer 是 Qt 提供的一个功能强大且灵活的 TCP 服务器类,通过本篇文章的学习,你应该对 QTcpServer 有了全面的理解,能够在自己的项目中正确使用它。QTcpServer 在用户界面中帮助你更好地管理和处理客户端连接,实现高效的 TCP 通信服务,有助于创建用户友好和高效的网络应用场景。


🧑 博主简介:现任阿里巴巴嵌入式技术专家,15年工作经验,深耕嵌入式+人工智能领域,精通嵌入式领域开发、技术管理、简历招聘面试。CSDN优质创作者,提供产品测评、学习辅导、简历面试辅导、毕设辅导、项目开发、C/C++/Java/Python/Linux/AI等方面的服务,如有需要请站内私信或者联系任意文章底部的的VX名片(ID:

gylzbk

💬 博主粉丝群介绍:① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。③ 群内也有职场精英,大厂大佬,可交流技术、面试、找工作的经验。④ 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬。⑤ 进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。

在这里插入图片描述
在这里插入图片描述

【QT开发】TCP服务器QTcpServer类详解及实战应用

    • 🌟 概述- 📖 QTcpServer 类介绍- - 常用方法- 常用信号- 💻 示例代码- - 示例:TCP 服务器- - 头文件:tcpserver.h- 主文件:main.cpp- 代码解释- 方法分析- 🧐 注意事项- 🛠️使用技巧- 📌总结

🌟 概述

QTcpServer 是 Qt 网络模块中的一个类,用于创建和管理 TCP 服务器。它提供了一套简洁且功能丰富的 API,使得开发者可以轻松地在 Qt 应用中搭建 TCP 服务器,用于接受客户端连接并进行数据通信。

QTcpServer 常用在需要提供网络服务的场景中,例如聊天服务器、文件传输服务器、远程控制等。

📖 QTcpServer 类介绍

在 Qt 官方文档中,

QTcpServer

类的定义如下:

classQTcpServer:publicQObject{
    Q_OBJECT
    // ...}

QTcpServer 继承自 QObject,是一个用于创建和管理 TCP 服务器的类。以下是一些关键特性和功能:

  • 监听连接:能够在指定的地址和端口上监听传入的连接请求。
  • 接受连接:处理传入的客户端连接请求,并生成 QTcpSocket 对象用于通信。
  • 连接管理:管理多个客户端连接,支持多客户端通信。
  • 信号与槽:提供丰富的信号与槽机制,方便处理连接、数据和错误事件。

常用方法

以下是 QTcpServer 类中一些常用的方法及其简要介绍:

  • 构造函数和析构函数:- QTcpServer(QObject *parent = nullptr):构造函数,创建一个 QTcpServer 对象。- ~QTcpServer():析构函数,销毁 QTcpServer 对象。
  • 服务启动和停止:- bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0):在指定的地址和端口上监听传入的连接请求。- void close():停止服务器,并断开所有现存连接。- bool isListening() const:判断服务器是否正在监听。
  • 连接管理:- QTcpSocket *nextPendingConnection():返回下一个等待处理的客户端连接。- int maxPendingConnections() const:返回最大待处理连接数。- void setMaxPendingConnections(int numConnections):设置最大待处理连接数。- bool hasPendingConnections() const:判断是否有待处理的客户端连接。
  • 状态查询:- QHostAddress serverAddress() const:返回服务器的地址。- quint16 serverPort() const:返回服务器的端口。- QString errorString() const:返回最后一个错误的描述。

常用信号

以下是 QTcpServer 类中一些常用的信号及其简要介绍:

  • void newConnection():当有新的客户端连接时发出信号。
  • void acceptError(QAbstractSocket::SocketError socketError):当接受连接时发生错误发出信号。

💻 示例代码

下面是一个简单的示例,用来演示如何使用 QTcpServer 创建一个基本的 TCP 服务器。该示例展示了一个带有按钮和文本编辑区域的窗口,启动服务器后可以接受客户端连接,并进行简单的通信。

示例:TCP 服务器

头文件:tcpserver.h
#ifndefTCPSERVER_H#defineTCPSERVER_H#include<QTcpServer>#include<QTcpSocket>#include<QObject>classTcpServer:publicQTcpServer{
    Q_OBJECT

public:TcpServer(QObject *parent =nullptr);protected:voidincomingConnection(qintptr socketDescriptor)override;

signals:voidnewMessage(const QString &message);};#endif// TCPSERVER_H
主文件:main.cpp
#include<QApplication>#include<QMainWindow>#include<QPushButton>#include<QVBoxLayout>#include<QTextEdit>#include<QTcpSocket>#include"tcpserver.h"classMainWindow:publicQMainWindow{
    Q_OBJECT

public:MainWindow(QWidget *parent =nullptr):QMainWindow(parent){setWindowTitle("QTcpServer Example");resize(400,300);// 创建服务器对象
        server =newTcpServer(this);// 创建UI组件
        QPushButton *startButton =newQPushButton("Start Server");
        outputTextEdit =newQTextEdit();
        outputTextEdit->setReadOnly(true);// 连接信号和槽connect(startButton,&QPushButton::clicked,this,&MainWindow::startServer);connect(server,&TcpServer::newMessage,this,&MainWindow::appendMessage);// 布局管理
        QVBoxLayout *layout =new QVBoxLayout;
        layout->addWidget(startButton);
        layout->addWidget(outputTextEdit);
        QWidget *centralWidget =new QWidget;
        centralWidget->setLayout(layout);setCentralWidget(centralWidget);}private slots:voidstartServer(){if(server->listen(QHostAddress::Any,1234)){
            outputTextEdit->append("Server started on port 1234");}else{
            outputTextEdit->append("Failed to start server: "+ server->errorString());}}voidappendMessage(const QString &message){
        outputTextEdit->append("Received: "+ message);}private:
    TcpServer *server;
    QTextEdit *outputTextEdit;};TcpServer::TcpServer(QObject *parent):QTcpServer(parent){}voidTcpServer::incomingConnection(qintptr socketDescriptor){
    QTcpSocket *socket =newQTcpSocket();if(socket->setSocketDescriptor(socketDescriptor)){connect(socket,&QTcpSocket::readyRead,this,[this, socket](){while(socket->canReadLine()){
                QByteArray line = socket->readLine().trimmed();
                emit newMessage(QString::fromUtf8(line));// Echo the message back to the client
                socket->write(line +"\n");}});connect(socket,&QTcpSocket::disconnected, socket,&QTcpSocket::deleteLater);}else{delete socket;}}intmain(int argc,char*argv[]){
    QApplication app(argc, argv);// 创建主窗口并显示
    MainWindow mainWindow;
    mainWindow.show();return app.exec();}#include"main.moc"

代码解释

  • 创建主窗口,并设置其标题和大小:MainWindow(QWidget *parent =nullptr):QMainWindow(parent){setWindowTitle("QTcpServer Example");resize(400,300);}
  • 创建 QTcpServer 派生类 TcpServer,并重载 incomingConnection() 函数:classTcpServer:publicQTcpServer{ Q_OBJECTpublic:TcpServer(QObject *parent =nullptr);protected:voidincomingConnection(qintptr socketDescriptor)override;signals:voidnewMessage(const QString &message);};
  • 在 TcpServer 类中实现 incomingConnection() 函数,处理新客户端连接:voidTcpServer::incomingConnection(qintptr socketDescriptor){ QTcpSocket *socket =newQTcpSocket();if(socket->setSocketDescriptor(socketDescriptor)){connect(socket,&QTcpSocket::readyRead,this,[this, socket](){while(socket->canReadLine()){ QByteArray line = socket->readLine().trimmed(); emit newMessage(QString::fromUtf8(line));// Echo the message back to the client socket->write(line +"\n");}});connect(socket,&QTcpSocket::disconnected, socket,&QTcpSocket::deleteLater);}else{delete socket;}}
  • 创建 UI 组件,包括按钮和文本编辑区域:QPushButton *startButton =newQPushButton("Start Server");outputTextEdit =newQTextEdit();outputTextEdit->setReadOnly(true);
  • 连接按钮的点击信号到槽函数,以及服务器的新消息信号到槽函数:connect(startButton,&QPushButton::clicked,this,&MainWindow::startServer);connect(server,&TcpServer::newMessage,this,&MainWindow::appendMessage);
  • 布局管理,将 UI 组件添加到窗口中央控件中:QVBoxLayout *layout =new QVBoxLayout;layout->addWidget(startButton);layout->addWidget(outputTextEdit);QWidget *centralWidget =new QWidget;centralWidget->setLayout(layout);setCentralWidget(centralWidget);
  • 实现槽函数 startServer,启动服务器监听:voidstartServer(){if(server->listen(QHostAddress::Any,1234)){ outputTextEdit->append("Server started on port 1234");}else{ outputTextEdit->append("Failed to start server: "+ server->errorString());}}
  • 实现槽函数 appendMessage,显示接收到的消息:voidappendMessage(const QString &message){ outputTextEdit->append("Received: "+ message);}
  • 启动 Qt 事件循环:return app.exec();

方法分析

  1. bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0):在指定的地址和端口上监听传入的连接请求。boollisten(const QHostAddress &address = QHostAddress::Any, quint16 port =0)用于在指定的地址和端口上监听传入的连接请求。
  2. void close():停止服务器,并断开所有现存连接。voidclose()用于停止服务器,并断开所有现存连接。
  3. bool isListening() const:判断服务器是否正在监听。boolisListening()const用于判断服务器是否正在监听。
  4. QTcpSocket *nextPendingConnection():返回下一个等待处理的客户端连接。QTcpSocket*nextPendingConnection()用于返回下一个等待处理的客户端连接。
  5. int maxPendingConnections() const:返回最大待处理连接数。intmaxPendingConnections()const用于返回最大待处理连接数。
  6. void setMaxPendingConnections(int numConnections):设置最大待处理连接数。voidsetMaxPendingConnections(int numConnections)用于设置最大待处理连接数。
  7. bool hasPendingConnections() const:判断是否有待处理的客户端连接。boolhasPendingConnections()const用于判断是否有待处理的客户端连接。
  8. QHostAddress serverAddress() const:返回服务器的地址。QHostAddress serverAddress()const用于返回服务器的地址。
  9. quint16 serverPort() const:返回服务器的端口。quint16 serverPort()const用于返回服务器的端口。
  10. QString errorString() const:返回最后一个错误的描述。QString errorString()const

用于返回最后一个错误的描述。

🧐 注意事项

  1. 线程安全:在处理客户端连接和数据通信时,注意线程安全问题。可以使用 QThread 将每个连接放到独立的线程中处理。
  2. 资源释放:在服务器关闭和客户端断开连接时,确保适当地释放资源,防止内存泄漏。
  3. 错误处理:在处理网络通信时,注意处理各种可能的错误情况,如连接失败、数据传输错误等。
  4. 数据协议:在实现具体的应用时,需要定义好通信的协议和数据格式,确保客户端和服务器能够正确地解析和处理数据。

🛠️使用技巧

  1. 多线程处理:通过将每个客户端连接放到独立的线程中处理,可以提高服务器的并发处理能力。classConnectionHandler:publicQThread{ Q_OBJECTpublic:ConnectionHandler(qintptr socketDescriptor, QObject *parent =nullptr):QThread(parent),socketDescriptor(socketDescriptor){}voidrun()override{ QTcpSocket socket; socket.setSocketDescriptor(socketDescriptor);// 处理连接和数据通信exec();}private: qintptr socketDescriptor;};voidTcpServer::incomingConnection(qintptr socketDescriptor){ ConnectionHandler *handler =newConnectionHandler(socketDescriptor); handler->start();}
  2. 心跳检测:通过定期发送心跳包,实现对客户端连接的健康检测,及时断开失效连接。QTimer *heartbeatTimer =newQTimer(this);connect(heartbeatTimer,&QTimer::timeout,this,[this](){// 发送心跳包});heartbeatTimer->start(30000);// 每30秒发送一次心跳包
  3. SSL加密通信:通过使用 QSslSocket,可以实现 SSL 加密的通信,保证数据传输的安全性。#include<QSslSocket>QSslSocket *sslSocket =newQSslSocket(this);sslSocket->setLocalCertificate("server.crt");sslSocket->setPrivateKey("server.key");sslSocket->startServerEncryption();
  4. 负载均衡:在高并发的场景下,可以通过负载均衡将客户端请求分发到多个服务器实例,提高处理能力。// 使用负载均衡器分发客户端请求
  5. 日志记录:在服务器中添加日志记录功能,可以方便地调试和监控服务器的运行状态。voidlogMessage(const QString &message){ QFile logFile("server.log");if(logFile.open(QIODevice::Append | QIODevice::Text)){ QTextStream out(&logFile); out << message <<"\n";}}

📌总结

QTcpServer 是 Qt 提供的一个功能强大且灵活的 TCP 服务器类,通过本篇文章的学习,你应该对 QTcpServer 有了全面的理解,能够在自己的项目中正确使用它。QTcpServer 在用户界面中帮助你更好地管理和处理客户端连接,实现高效的 TCP 通信服务,有助于创建用户友好和高效的网络应用场景。

标签: qt tcp/ip 服务器

本文转载自: https://blog.csdn.net/g310773517/article/details/140329553
版权归原作者 I'mAlex 所有, 如有侵权,请联系我们删除。

“【QT开发】TCP服务器QTcpServer类详解及实战应用”的评论:

还没有评论