From 2f3c6001d6da20c8490c3b96763a2f86cc1e19f4 Mon Sep 17 00:00:00 2001 From: Vicx95 Date: Thu, 28 Mar 2024 23:05:13 +0100 Subject: [PATCH] Implement basic version of web socket server #19 Create initial CMakeList Implement basic version of chat server --- server/CMakeLists.txt | 25 +++++++++++++++++++ server/chatserver.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++ server/chatserver.h | 23 ++++++++++++++++++ server/main.cpp | 10 ++++++++ 4 files changed, 114 insertions(+) create mode 100644 server/CMakeLists.txt create mode 100644 server/chatserver.cpp create mode 100644 server/chatserver.h create mode 100644 server/main.cpp diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..25781a5 --- /dev/null +++ b/server/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.14) + +project(server LANGUAGES CXX) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core WebSockets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core WebSockets) + +add_executable(server + main.cpp + chatserver.h chatserver.cpp +) +target_link_libraries(server Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::WebSockets) + +include(GNUInstallDirs) +install(TARGETS server + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/server/chatserver.cpp b/server/chatserver.cpp new file mode 100644 index 0000000..3a8977f --- /dev/null +++ b/server/chatserver.cpp @@ -0,0 +1,56 @@ +#include "chatserver.h" + +static QString getIdentifier(QWebSocket* socket) +{ + return QStringLiteral("%1:%2").arg(socket->peerAddress().toString(), + QString::number(socket->peerPort())); +} + +ChatServer::ChatServer(quint16 port, QObject *parent) + : QObject{parent}, + m_webSocketServer{new QWebSocketServer("Chat Server", + QWebSocketServer::NonSecureMode, + this)} +{ + if(m_webSocketServer->listen(QHostAddress::Any, port)) + { + qInfo() << "Server listening on port " << port; + connect(&*m_webSocketServer, &QWebSocketServer::newConnection, this, &ChatServer::onNewConnection); + } +} + +ChatServer::~ChatServer(){ + m_webSocketServer->close(); +} + +void ChatServer::onNewConnection() +{ + auto clientSocket = m_webSocketServer->nextPendingConnection(); + qInfo() << getIdentifier(clientSocket) << " connected!"; + clientSocket->setParent(this); + + connect(clientSocket, &QWebSocket::textMessageReceived, this, &ChatServer::processMessage); + connect(clientSocket, &QWebSocket::disconnected, this, &ChatServer::socketDisconnected); + + m_clients << clientSocket; +} + +void ChatServer::processMessage(const QString& message) +{ + QWebSocket* clientSender = qobject_cast(sender()); + for (QWebSocket* client : std::as_const(m_clients)) { + if (client != clientSender) + client->sendTextMessage(message); + } +} + +void ChatServer::socketDisconnected() +{ + QWebSocket* client = qobject_cast(sender()); + qInfo() << getIdentifier(client) << " disconnected!"; + if(client) + { + m_clients.removeAll(client); + client->deleteLater(); + } +} diff --git a/server/chatserver.h b/server/chatserver.h new file mode 100644 index 0000000..52d5430 --- /dev/null +++ b/server/chatserver.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include +#include + +class ChatServer : public QObject +{ + Q_OBJECT +public: + explicit ChatServer(quint16 port, QObject *parent = nullptr); + ~ChatServer() override; + +private slots: + void onNewConnection(); + void processMessage(const QString& message); + void socketDisconnected(); + +private: + QWebSocketServer* m_webSocketServer; + QList m_clients; +}; diff --git a/server/main.cpp b/server/main.cpp new file mode 100644 index 0000000..0b56203 --- /dev/null +++ b/server/main.cpp @@ -0,0 +1,10 @@ +#include +#include "chatserver.h" + +int main(int argc, char *argv[]) { + QCoreApplication a(argc, argv); + + ChatServer server(2000); + + return a.exec(); +}