Qt实现简易的多线程TCP服务器(附源码)

本文详细描述了如何在Qt中使用多线程和自定义类实现一个简易的Tcp服务器,包括UI界面设计、服务器启动、自定义TcpServer和TcpSocket类,以及线程间的通信和消息处理。作者通过实例展示了如何在服务器接收到新连接、客户端断开和消息发送时更新主界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.UI界面的设计

二.服务器的启动

三.实现自定义的TcpServer类

1.在widget中声明自定义TcpServer类的成员变量

2.在TcpServer的构造函数中对于我们声明的m_widget进行初始化,m_widget我们用于后续的显示消息等,说白了就是主界面的更新显示等

四.实现自定义的TcpSocket类

1.TcpSocket.h   先忽略掉信号与槽函数,关注构造函数与qintptr类型的 m_sockDesc

五.实现自定义线程类

1.主要关注run函数,其中run函数是继承QThread中的虚函数,需要我们进行重写

2.实现某个客户端断开连接时通过信号与槽让主界面改变

3.实现有新的客户端连接时主界面更新

六.服务器收到多客户端消息进行显示的流程实现

七.服务器发送消息给某个客户端流程

八.服务器发送信息后,要在主页面信息消息更新显示的流程

注意:

效果演示:

源码下载地址:


在初学Qt 中Tcp服务器与客户端的时候,发现每次服务器只能和最后一个连接的客户端进行通信,因为没有用到多线程以及TcpServer中虚函数incomingConnection(),当新的客户端连接的时候,会自动调用incomingConnection函数,在里面产生新的线程来处理通信。

以下来讲讲这个简易的多线程Tcp服务器的实现

一.UI界面的设计

其中包括2个Label,一个LineEdit,两个pushbutton,上面是一个TextBrowser用于服务器显示通信记录,下面一个TextEdit用于发送信息。这样一个简单的界面就搭建完成了~~~

二.服务器的启动

首先我们肯定需要实现点击启动服务器按钮来启动服务器

1.在界面中右击启动按钮 ----> 转到槽

2.实现逻辑,这里直接放代码,其中serverisworking 是我在widget.h 中声明的一个bool类型,用于判断服务器是否启动,同时更改按钮的文本显示内容,以及弹出对话框提示。

//点击开始启动服务器
void Widget::on_pushButton_StartServer_clicked()
{
    //如果服务器没有启动
     if (!this->serverisworking) {
        if(this->m_tcpserver->listen(QHostAddress::Any,ui->lineEdit_Port->text().toUShort())){
            QMessageBox::information(this,"成功!","启动成功!");
            ui->pushButton_StartServer->setText("关闭服务器");
            this->serverisworking = true;
        }
        else {
            QMessageBox::critical(this,"失败!","服务器启动失败请检查设置!");
        }
    }
    //如果服务器正在启动
     else if(this->serverisworking) {
         m_tcpserver->close();
         if(!m_tcpserver->isListening()){
             ui->pushButton_StartServer->setText("启动服务器");
             this->serverisworking = false;
             QMessageBox::information(this,"提示","关闭成功!");
         }
         else {
             QMessageBox::critical(this,"错误","关闭失败,请重试!");
             return;
         }

     }
}

三.实现自定义的TcpServer类

1.首先我们搞清楚,这个类是负责干嘛的?这个类我们要继承QTcpServer,重写虚函数incomingConnetion

2.这是头文件,如果有报错,注意看使用#pragma once没有,因为可能涉及到头文件重复包含

//tcpserver.h
#pragma once
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QObject>
#include<QTcpServer>

#include <widget.h>
#include"serverthread.h"

class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit TcpServer(QObject *parent = nullptr);

private:

    //重写虚函数
    void incomingConnection(qintptr sockDesc);

private:
    
    //用来保存连接进来的套接字,存到ComboBox中
    QList<qintptr> m_socketList;
    
    //再包含一个widget对象
    Widget *m_widget;

};

#endif // TCPSERVER_H

1.在widget中声明自定义TcpServer类的成员变量

//widget.h
#pragma once
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QMessageBox>
#include"tcpserver.h"

namespace Ui {
class Widget;
}

class TcpServer;

class Widget : public QWidget
{
    Q_OBJECT

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

public:
    //当有新连接的时候在页面上显示
    void showNewConnection(qintptr sockDesc);

    //断开时显示
    void showDisconnection(qintptr sockDesc);

    //当服务器发送消息后,通知窗口更新消息
    void UpdateServerMsg(qintptr Desc,const QByteArray &msg);


private slots:

    //按钮被触发
    void on_pushButton_StartServer_clicked();

    void on_pushButton_Trans_clicked();


public slots:

    //当服务器收到客户端发送的消息后,更新消息
    void RecvMsg(QString Desc,const QByteArray &msg);


signals :
   void  sendData(qintptr Desc ,const QByteArray &msg);

private:
    Ui::Widget *ui;

    TcpServer *m_tcpserver;

    bool serverisworking;
};

#endif // WIDGET_H

其他的我们先不去讨论,这里我们就声明一个TcpServer类型的m_tcpserver 以及一个bool类型的serverisworking用来判断服务器是否在工作

2.在TcpServer的构造函数中对于我们声明的m_widget进行初始化,m_widget我们用于后续的显示消息等,说白了就是主界面的更新显示等

TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
{
     m_widget = dynamic_cast&
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值