282 lines
6.9 KiB
C++
282 lines
6.9 KiB
C++
|
|
#include "VrTcpServer.h"
|
||
|
|
#include <QTcpServer>
|
||
|
|
#include <QTcpSocket>
|
||
|
|
#include <QUuid>
|
||
|
|
#include <QDebug>
|
||
|
|
|
||
|
|
VrTcpServer::VrTcpServer(QObject *parent)
|
||
|
|
: IVrTcpServer(parent)
|
||
|
|
, m_server(new QTcpServer(this))
|
||
|
|
, m_port(0)
|
||
|
|
{
|
||
|
|
// 连接服务器信号
|
||
|
|
connect(m_server, &QTcpServer::newConnection, this, &VrTcpServer::onNewConnection);
|
||
|
|
connect(m_server, &QTcpServer::acceptError, this, [this](QAbstractSocket::SocketError error) {
|
||
|
|
emit serverError(m_server->errorString());
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
VrTcpServer::~VrTcpServer()
|
||
|
|
{
|
||
|
|
stopServer();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool VrTcpServer::startServer(quint16 port)
|
||
|
|
{
|
||
|
|
if (m_server->isListening()) {
|
||
|
|
stopServer();
|
||
|
|
}
|
||
|
|
|
||
|
|
m_port = port;
|
||
|
|
bool result = m_server->listen(QHostAddress::Any, port);
|
||
|
|
|
||
|
|
if (result) {
|
||
|
|
emit serverStarted();
|
||
|
|
} else {
|
||
|
|
emit serverError(m_server->errorString());
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::stopServer()
|
||
|
|
{
|
||
|
|
// 断开所有客户端连接
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
it.value()->disconnectFromHost();
|
||
|
|
}
|
||
|
|
m_clients.clear();
|
||
|
|
|
||
|
|
// 停止服务器监听
|
||
|
|
if (m_server->isListening()) {
|
||
|
|
m_server->close();
|
||
|
|
emit serverStopped();
|
||
|
|
}
|
||
|
|
|
||
|
|
m_port = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool VrTcpServer::isListening() const
|
||
|
|
{
|
||
|
|
return m_server->isListening();
|
||
|
|
}
|
||
|
|
|
||
|
|
quint16 VrTcpServer::serverPort() const
|
||
|
|
{
|
||
|
|
return m_port;
|
||
|
|
}
|
||
|
|
|
||
|
|
QStringList VrTcpServer::getClientIds() const
|
||
|
|
{
|
||
|
|
return m_clients.keys();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool VrTcpServer::disconnectClient(const QString &clientId)
|
||
|
|
{
|
||
|
|
if (!m_clients.contains(clientId)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
QTcpSocket *socket = m_clients[clientId];
|
||
|
|
socket->disconnectFromHost();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
qint64 VrTcpServer::sendDataToClient(const QString &clientId, const QByteArray &data)
|
||
|
|
{
|
||
|
|
if (!m_clients.contains(clientId)) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
QTcpSocket *socket = m_clients[clientId];
|
||
|
|
if (socket->state() != QAbstractSocket::ConnectedState) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return socket->write(data);
|
||
|
|
}
|
||
|
|
|
||
|
|
qint64 VrTcpServer::sendDataToClient(const QString &clientId, const char *data, qint64 size)
|
||
|
|
{
|
||
|
|
if (!m_clients.contains(clientId)) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
QTcpSocket *socket = m_clients[clientId];
|
||
|
|
if (socket->state() != QAbstractSocket::ConnectedState) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return socket->write(data, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
QHostAddress VrTcpServer::getClientAddress(const QString &clientId) const
|
||
|
|
{
|
||
|
|
if (!m_clients.contains(clientId)) {
|
||
|
|
return QHostAddress();
|
||
|
|
}
|
||
|
|
|
||
|
|
return m_clients[clientId]->peerAddress();
|
||
|
|
}
|
||
|
|
|
||
|
|
quint16 VrTcpServer::getClientPort(const QString &clientId) const
|
||
|
|
{
|
||
|
|
if (!m_clients.contains(clientId)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return m_clients[clientId]->peerPort();
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::onNewConnection()
|
||
|
|
{
|
||
|
|
while (m_server->hasPendingConnections()) {
|
||
|
|
QTcpSocket *socket = m_server->nextPendingConnection();
|
||
|
|
|
||
|
|
// 生成客户端ID
|
||
|
|
QString clientId = generateClientId(socket);
|
||
|
|
|
||
|
|
// 存储客户端连接
|
||
|
|
m_clients[clientId] = socket;
|
||
|
|
|
||
|
|
// 连接客户端信号
|
||
|
|
connect(socket, &QTcpSocket::disconnected, this, &VrTcpServer::onClientDisconnected);
|
||
|
|
connect(socket, &QTcpSocket::readyRead, this, &VrTcpServer::onClientReadyRead);
|
||
|
|
connect(socket, &QTcpSocket::bytesWritten, this, &VrTcpServer::onClientBytesWritten);
|
||
|
|
|
||
|
|
// 发送客户端连接信号
|
||
|
|
emit clientConnected(clientId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::onClientDisconnected()
|
||
|
|
{
|
||
|
|
QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
|
||
|
|
if (!socket) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查找断开连接的客户端ID
|
||
|
|
QString clientId;
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
if (it.value() == socket) {
|
||
|
|
clientId = it.key();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!clientId.isEmpty()) {
|
||
|
|
m_clients.remove(clientId);
|
||
|
|
emit clientDisconnected(clientId);
|
||
|
|
}
|
||
|
|
|
||
|
|
socket->deleteLater();
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::onClientReadyRead()
|
||
|
|
{
|
||
|
|
QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
|
||
|
|
if (!socket) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查找客户端ID
|
||
|
|
QString clientId;
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
if (it.value() == socket) {
|
||
|
|
clientId = it.key();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!clientId.isEmpty()) {
|
||
|
|
QByteArray data = socket->readAll();
|
||
|
|
if (!data.isEmpty()) {
|
||
|
|
emit dataReceived(clientId, data);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::onClientBytesWritten(qint64 bytes)
|
||
|
|
{
|
||
|
|
QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
|
||
|
|
if (!socket) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查找客户端ID
|
||
|
|
QString clientId;
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
if (it.value() == socket) {
|
||
|
|
clientId = it.key();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!clientId.isEmpty()) {
|
||
|
|
emit dataSent(clientId, bytes);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void VrTcpServer::onServerError(QAbstractSocket::SocketError error)
|
||
|
|
{
|
||
|
|
Q_UNUSED(error)
|
||
|
|
QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
|
||
|
|
if (!socket) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查找客户端ID
|
||
|
|
QString clientId;
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
if (it.value() == socket) {
|
||
|
|
clientId = it.key();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!clientId.isEmpty()) {
|
||
|
|
emit serverError(QString("Client %1 error: %2").arg(clientId, socket->errorString()));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
QString VrTcpServer::generateClientId(QTcpSocket *socket)
|
||
|
|
{
|
||
|
|
// 使用UUID生成唯一的客户端ID
|
||
|
|
return QUuid::createUuid().toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
qint64 VrTcpServer::broadcastData(const QByteArray &data)
|
||
|
|
{
|
||
|
|
qint64 totalBytesWritten = 0;
|
||
|
|
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
QTcpSocket *socket = it.value();
|
||
|
|
if (socket->state() == QAbstractSocket::ConnectedState) {
|
||
|
|
qint64 bytesWritten = socket->write(data);
|
||
|
|
if (bytesWritten > 0) {
|
||
|
|
totalBytesWritten += bytesWritten;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return totalBytesWritten;
|
||
|
|
}
|
||
|
|
|
||
|
|
qint64 VrTcpServer::broadcastData(const char *data, qint64 size)
|
||
|
|
{
|
||
|
|
qint64 totalBytesWritten = 0;
|
||
|
|
|
||
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
|
||
|
|
QTcpSocket *socket = it.value();
|
||
|
|
if (socket->state() == QAbstractSocket::ConnectedState) {
|
||
|
|
qint64 bytesWritten = socket->write(data, size);
|
||
|
|
if (bytesWritten > 0) {
|
||
|
|
totalBytesWritten += bytesWritten;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return totalBytesWritten;
|
||
|
|
}
|