QTcpServer多客户端连接

Qt默认的QTcpServer有新的连接时会触发newConnection信号,在其对应的槽函数中new QTcpSocket,
通过new的QTcpSocket对象接受发送数据,当有多客户端连接时,Server端接受的数据将不容易分辨是哪个客户端的socket发送的数据,解决这个问题的办法是重写QTcpServer中的incomingConnection(qintptr handle)函数,当有新的连接时,会调用该函数,在该函数中new 一个Socket的,并将函数中的参数handle传递给new的socket作为该socket的ID,这样当有数据发送到server端的时候,就可以知道是哪个客户端的socket。这里需要派生一个QTcpSocketlei用于接收handle作为socket的ID。具体代码实现如下:

派生QTcpSocket:

#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include 
#include 

class TcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TcpSocket(const int handle);

    void slot_readData();
signals:
    void sig_disconnect(int);
    void sig_readyRead(int, const QByteArray&);

private slots:
    void slot_disconnect();

private:
    int m_handle;

};

#endif // TCPSOCKET_H

#include "TcpSocket.h"

TcpSocket::TcpSocket(const int handle) : m_handle(handle)
{
    this->setSocketDescriptor(m_handle);
    connect(this,&TcpSocket::disconnected,this,&TcpSocket::slot_disconnect);
    connect(this,&TcpSocket::readyRead,this,&TcpSocket::slot_readData); 
}

void TcpSocket::slot_disconnect()
{
    emit sig_disconnect(m_handle);
}

void TcpSocket::slot_readData()
{
    QByteArray data = readAll();
    emit sig_readyRead(m_handle, data);
}

派生QTcpServer,重写incomingConnection(qintptr handle)函数

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include 
#include 
#include "TcpSocket.h"

class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    TcpServer();

    virtual void incomingConnection(qintptr handle) override;

private slots:
    void slot_disconnect(int handle);
    void slot_readData(int handle, const QByteArray &data);
signals:
    void sig_disconnect(int);
    void sig_connect(int, QTcpSocket*);
    void sig_readyRead(int, const QByteArray &data);
private:

};

#endif // TCPSERVER_H

#include "TcpServer.h"

TcpServer::TcpServer()
{

}

void TcpServer::incomingConnection(qintptr handle)
{
    TcpSocket *socket = new TcpSocket(handle);

    connect(socket,SIGNAL(sig_disconnect(int)),this,SLOT(slot_disconnect(int)));
    connect(socket,&TcpSocket::sig_readyRead,this,&TcpServer::slot_readData);

    emit sig_connect(handle, socket);
}

void TcpServer::slot_disconnect(int handle)
{
    emit sig_disconnect(handle);
}

void TcpServer::slot_readData(int handle, const QByteArray &data)
{
    emit sig_readyRead(handle, data);
}

应用实例:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "TcpServer.h"
#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();

protected slots:
    void slot_readData(int handle, const QByteArray &data);
private slots:
    void slot_disconnect(int handle);
    void slot_connect(int handle, QTcpSocket *socket);
    void slot_timeout();
private:
    Ui::MainWindow *ui;

    TcpServer *m_tcpServer;

    QMap<int, QTcpSocket*> m_socketMap;   

    QTimer* m_timer;
};
#endif // MAINWINDOW_H

#include "MainWindow.h"
#include "ui_MainWindow.h"


#include 


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_tcpServer = new TcpServer();

    m_tcpServer->listen(QHostAddress::Any, 8000);
    connect(m_tcpServer,&TcpServer::sig_connect,this,&MainWindow::slot_connect);
    connect(m_tcpServer,SIGNAL(sig_disconnect(int)),this,SLOT(slot_disconnect(int)));
    connect(m_tcpServer,SIGNAL(sig_readyRead(int,QByteArray)),this,SLOT(slot_readData(int,QByteArray)));

    m_timer = new QTimer(this);
    connect(m_timer,&QTimer::timeout,this,&MainWindow::slot_timeout);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slot_connect(int handle, QTcpSocket *socket)
{
    qDebug()<<handle<<" connect";
    m_socketMap.insert(handle, socket);
    m_timer->start(2000);
}

void MainWindow::slot_timeout()
{
    QString data = QString("xxooxxooxxooxxooxxooxxooxxooxxooxxoo");
    for (auto socket : m_socketMap) {
        socket->write(data.toLatin1());
        qDebug()<<"write "<<data;
    }
}

void MainWindow::slot_disconnect(int handle)
{
    m_timer->stop();
    m_socketMap.remove(handle);
    qDebug()<<handle<<" disconnect";
}

void MainWindow::slot_readData(int handle, const QByteArray &data)
{
    qDebug()<<"handle "<<handle<<" data: "<<QString(data);

    QByteArray cmd = QString("sRA LMDscandata").toLatin1();
    char c = 0x00;
    cmd.append(c);
    cmd.append(0x01);
    cmd.append(QString("A05EE0").toLatin1());
    cmd.append(c);
    cmd.append(c);
    cmd.append(QString("227C").toLatin1());
    cmd.append(QString("495E").toLatin1());
    cmd.append(QString("65EE1D80").toLatin1());
    cmd.append(QString("66258D27").toLatin1());
    cmd.append(c);
    cmd.append(c);
    cmd.append(0x3F);

    m_socketMap.value(handle)->write(cmd);
}


你可能感兴趣的:(QTcpServer多客户端连接)