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