QT实现TCPServer连接多个客户端

QT实现Server连接一个客户端

在实现连接多个客户端之前首先需要知道连接一个客户端是怎么完成的,这里先放出代码的头文件,很多变量都是在这里定义的。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QVector>
#include <QNetworkInterface>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();




private slots:
    void on_Connect_Button_clicked();
    void server_New_Connect();
    void socket_Read_Data();
    void socket_Disconnected();


    void on_pushButton_clicked();

private:
    void Get_IP();

    Ui::MainWindow *ui;
    QTcpServer* server;
    QTcpSocket* socket;
    QList<QTcpSocket*> TcpSockets_List;
    int Client_num;
};
#endif // MAINWINDOW_H

本机IP地址的获取和显示

void MainWindow::Get_IP()
{
    QString strIpAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); 
    //这一行代码是核心,利用一个QList把本机的所有IP地址存储下来
    //例如我的电脑会有两个虚拟机的IP地址,一个无线网卡的IP地址,一个有线网卡的IP地址。
    int nListSize = ipAddressesList.size();
    strIpAddress = ipAddressesList.at(2).toString();//无线网阿卡的IP地址存在List的第三个地方
    ui->Current_IP->setText(strIpAddress);
}

侦听按钮的实现

检测按钮的文字是不是侦听,是的话就开始侦听,不然就取消侦听。

void MainWindow::on_Connect_Button_clicked()
{
    if(ui->Connect_Button->text() == tr("侦听"))
    {
        //从输入框获取端口号
        int port = ui->Net_Port->text().toInt();
        //监听指定的端口
        if(!server->listen(QHostAddress::Any, port))
        {
            //若出错,则输出错误信息
            qDebug()<<server->errorString();
            return;
        }
        //修改按键文字
        ui->Connect_Button->setText("取消侦听");
        qDebug()<< "Listen succeessfully!";
    }
    else
    {
        Client_num=0;
        ui->Client_num->setText(QString::number(Client_num));
        //取消侦听
        server->close();
        //修改按键文字
        ui->Connect_Button->setText("侦听");
    }
}

创建一个TCPServer对象,并且连接信号槽

    server = new QTcpServer();  //创建TcpServer对象
    connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);//连接信号槽

当新的客户端连接进来时

当有新的TCPClient链接进来的时候,就会运行server_New_Connect的槽函数

void MainWindow::server_New_Connect()   //当有新的链接来的时候
{
    //获取客户端连接
    socket = server->nextPendingConnection();
    QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
    Client_num++; //连接客户端的数量加一
    ui->Client_num->setText(QString::number(Client_num));
    qDebug() << "A Client connect!";
}

在这个函数中首先利用nextPendingConnection()这个函数来获取客户端的连接,然后把接收到数据和断开连接的信号连接到相应的槽函数并在下面实现。

读取客户端发送过来的数据和给客户端发送数据

这个函数是上面readyRead信号所连接的槽函数,在这个函数中把socket套接字对象里面的数据利用readAll()函数读取出来,并且加以显示

void MainWindow::socket_Read_Data()//当有数据过来之后读数据
{
    QByteArray buffer;
    buffer = socket->readAll();//读取缓冲区数据
	ui->Address_A->setText(buffer);
}

如果要给客户端发送数据,也是采用类似的方法,首先利用write函数来发送数据,然后用flush函数清除缓存。

void MainWindow::on_pushButton_clicked()
{

    socket->write("123");
	socket->flush();
}

QT实现Server连接一个客户端

接下来就是重头戏,怎么连接多个客户端并且进行处理

当新的客户端连接进来时的处理

由于有多个客户端,所以需要用一个QList来把所有的客户端给存起来,网上有些大神采用的多链接的方式是改写incomingConnection函数,但是本菜鸟不太会这种方法,所以直接在server_New_Connect这个槽函数中对连接进来的客户端进行了保存

void MainWindow::server_New_Connect()   //当有新的链接来的时候
{
    //获取客户端连接
    socket = server->nextPendingConnection();

    TcpSockets_List.append(socket);//把新进来的客户端存入列表
    ui->textBrowser->append("NewClient:" + socket->peerAddress().toString());
    //在文本框中显示新链接进来的客户端的IP地址

    //连接QTcpSocket的信号槽,以读取新数据
    QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
    Client_num++;
    ui->Client_num->setText(QString::number(Client_num));
    qDebug() << "A Client connect!";
}

多个客户端链接的时候的读写数据

读数据采用for循环循环列表中的每一个连接进来的客户端,看每个客户端的接收数据缓冲区的长度,如果不为0则代表是这个客户端发送的数据,就把数据取出来。

void MainWindow::socket_Read_Data()//当有数据过来之后读数据
{
    QByteArray buffer;
	//利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
    for(int i = 0; i < TcpSockets_List.count(); i++)
    {
        socket = TcpSockets_List.at(i); 
        buffer = socket->readAll();
        if(buffer.length()!=0)   //如果检测到接收到的数据长度不为0,则代表是这个客户端发送的数据
            ui->Address_A->setText(buffer);
    }
}

写数据的时候目前采用的是广播的形式,给每个连接上的客户端都发送数据

void MainWindow::on_pushButton_clicked()
{
    for(int i = 0; i < TcpSockets_List.count(); i++)
    {
        socket = TcpSockets_List.at(i);
        socket->write("123");
    }
    socket->flush();
}

这就是TCPServer连接多客户端的方法。

测试效果

首先开启侦听后用自己的手机和电脑连接这个Server,并且发送123后,可以看到左上角的文本框内容变成了123
右边发送123,左边显示
然后点击发送测试按钮以后,右边的网络调试助手和手机上的调试助手都接受到了发送的文本数据123
在这里插入图片描述
在这里插入图片描述

感谢您的观看,由于本人水平有限,部分内容可能描述的不够清楚,希望大佬们批评指正!

  • 21
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值