Qt 客户端和服务器通信【1对N版本】



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

.h文件

form.h [客户端]

#ifndef FORM_H
#define FORM_H

#include <QWidget>
#include <QTimer>
#include <QTcpSocket>

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

mainwindow.h [服务器]

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>//服务器类
#include <QTcpSocket>
#include <QVector>

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

.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;
}

mainwindow.cpp [服务器]

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>

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;
}


main.cpp

这里创建了客户端数组

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

#include "mainwindow.h"
#include "form.h"

#include <QApplication>

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();
}

实现细节

实现多客户端接受

通过再服务器端声明QTCPSocket类来接受客户端的数据实现对多个客户端的记录
QVector <QTcpSocket> 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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值