• Qt 客户端和服务器通信【一对一版本】




    【注意这里是服务器向多个客户端发起广播,不支持客户端通过服务器与另一个服务器进行沟通(后续会进行更新)】

    .h文件

    form.h [客户端]

    #ifndef FORM_H
    #define FORM_H
    
    #include 
    #include 
    #include 
    
    namespace Ui {
    class Form;
    }
    
    class Form : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Form(QWidget *parent = nullptr);
        ~Form();
    
    private:
        Ui::Form *ui;
    
         QTcpSocket  *kehuduan;
    };
    
    #endif // FORM_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    mainwindow.h [服务器]

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include //服务器类
    #include 
    #include 
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        QTcpServer *server;
        //QTcpSocket  *kehuduan;
        QVector <QTcpSocket*> ret;
    
    private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    .cpp文件

    form.cpp [客户端]

    #include "form.h"
    #include "ui_form.h"
    
    
    Form::Form(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Form)
    {
    
        //客户端
        ui->setupUi(this);
        //实例化服务器对象(this自动释放)
        kehuduan= new QTcpSocket(this);
        setWindowTitle("客户端1");
        ui->lineEdit_ip->setText("127.0.0.1");
        ui->lineEdit_duankou->setText("8888");
        ui->pushButton_duankou->setText("端口未连接");
    
        QTimer *time1 = new QTimer(this);
        time1->setInterval(1000);
        time1->start();
    //    connect(time1,&QTimer::timeout,this,[=](){
    //        if(    ui->pushButton_duankou->text() == "端口已连接"){
    //                ui->pushButton_duankou->setText("端口未连接");
    //                kehuduan->close();//断开连接
    //                //kehuduan->deleteLater();//删除实例化对象
    //                return ;
    //        }
    //    });
    //    connect(ui->pushButton_duankou,&QPushButton::clicked,this,[=](){
    //        time1->timeout(1);
    //    });
    
    //连接服务器
        connect(ui->pushButton_duankou,&QPushButton::clicked ,[=](){
            if(    ui->pushButton_duankou->text() == "端口已连接"){
                    ui->pushButton_duankou->setText("端口未连接");
                    //释放标志
                    QString str ="%close%";
                    //QString转char* 。toutf8
                    kehuduan->write(str.toUtf8());
                    ui->textBrowser->append("客户端1退出连接");
                    kehuduan->close();
    
                    //kehuduan->deleteLater();
                    return;
            }
            QString ip = ui->lineEdit_ip->text();
            unsigned short  port = ui->lineEdit_duankou->text().toUShort();
            //连接服务器
            kehuduan->connectToHost(ip,port);
              ui->pushButton_duankou->setText("端口已连接");
            //ui->pushButton_duankou->setDisabled(true);
        });
    
    //给客户端发送数据
        connect(ui->pushButton_fasong,&QPushButton::clicked,this,[=](){
            QString str = this->windowTitle()+":"+ ui->textEdit->toPlainText();
            //QString转char* 。toutf8
            kehuduan->write(str.toUtf8());
            ui->textBrowser->append(str);
        });
        connect(kehuduan,&QTcpSocket::readyRead,this,[=](){
            QByteArray data = kehuduan->readAll();
            ui->textBrowser->append("服务端:"+data);
        });
    
    }
    
    Form::~Form()
    {
        delete ui;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    mainwindow.cpp [服务器]

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include 
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        //服务器端
        ui->setupUi(this);
        //实例化服务器对象(this自动释放)
        server = new QTcpServer(this);
        ui->lineEdit_duankou->setText("8888");
    
    //启动监听按钮【无问题】
        connect(ui->pushButton_duankou,&QPushButton::clicked,[=](){
            unsigned short  port = ui->lineEdit_duankou->text().toUShort();
            //开监听【ip+port】
            server->listen(QHostAddress::Any,port);
            ui->pushButton_duankou->setDisabled(true);
        });
    
    //等待客户端连接【无问题】
            connect(server,&QTcpServer::newConnection,this,[=](){
             //   kehuduan = server->nextPendingConnection();
                ret.push_back(server->nextPendingConnection());
                int len = ret.size();
                 QMessageBox::information(this,"通知",QString("现有客户端数量%1").arg(ret.size()));
    
                for(int i=0 ; i != len ; i++){
                connect(ret[i],&QTcpSocket::readyRead,this,[=](){
                    QByteArray data = ret[i]->readAll();
                    if(data == "%close%") {
                       ret.erase(ret.begin()+i);
                       //ret.resize(ret.size()-1);
                       QMessageBox::information(this,"通知",QString("现有数量%1").arg(ret.size()));
                    }
                    if(data != NULL)
                    ui->textBrowser->append(data);
                });
                }
            });
    //给客户端发送数据
        connect(ui->pushButton_fasong,&QPushButton::clicked,this,[=](){
            QString str = ui->textEdit->toPlainText();
            //QString转char* 。toutf8
            for(int i=0 ; i<ret.size() ; i++){
            ret[i]->write(str.toUtf8());
    
            }
                 ui->textBrowser->append("服务端:"+str);
        });
    
    }
    
    MainWindow::~MainWindow()
    {
        //如果不指定要在析构delete
        delete ui;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    main.cpp

    这里创建了客户端数组

    可以通过改变main.cpp里的len改变客户端数量

    #include "mainwindow.h"
    #include "form.h"
    
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        int len = 2;
        Form *f = new  Form[len];
        for(int i=0 ; i<len ; i++){
            f[i].setWindowTitle(QString("客户端%1").arg(i+1));
           f[i].show();
        }
    
    //    client2 c2;
    //    c2.show();
    //    client3 c3;
    //    c3.show();
        return a.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    实现细节

    实现多客户端接受

    通过再服务器端声明QTCPSocket类来接受客户端的数据实现对多个客户端的记录
    QVector > ret;*
    【注意这里是通过遍历一遍vector容器来判断是谁发来了数据,一旦客户端过多性能会不佳】

    遍历和删除细节

    for(int i=0 ; i != ret.size(); i++)//这里最佳的遍历结束符应当是!=而不是<
    ret.erase(ret.begin()+i); //删除erase而不是swap()和pop_back();

    效果图

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

    代码压缩包

    https://pan.baidu.com/s/1oHVA1Fo_AOxN1h0go415Sg
    提取码:5v6b

  • 相关阅读:
    免费的visual studio智能代码插件——CodeGeeX
    225. 用队列实现栈、232. 用栈实现队列、622. 设计循环队列
    Centos7安装wps无法打开及字体缺失的问题解决
    时间不确定度在分布式系统中的说明
    工业场景全流程!机器学习开发并部署服务到云端 ⛵
    Java编程之道:巧妙解决Excel公式迭代计算难题
    肖sir_测试点
    前端开发:Vue混入(mixin)的使用
    [硬件基础]-555定时器-单稳态多谐振荡器配置
    ant target的if和unless属性:控制target是否执行
  • 原文地址:https://blog.csdn.net/weixin_45646601/article/details/126904777