From 9bac5ca34a6e337b63ffc08a69605c299955c2cd Mon Sep 17 00:00:00 2001 From: ackimixs Date: Thu, 21 Mar 2024 18:29:07 +0100 Subject: [PATCH] Omg v4 ? --- CMakeLists.txt | 8 +-- ModelecServer.cpp | 33 ----------- ModelecServer.h | 15 ----- TCPServer.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++ TCPServer.h | 56 ++++++++++++++++++ main.cpp | 2 +- 6 files changed, 204 insertions(+), 55 deletions(-) delete mode 100644 ModelecServer.cpp delete mode 100644 ModelecServer.h create mode 100644 TCPServer.cpp create mode 100644 TCPServer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e6f1b7..b2c8025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,6 @@ project(socketServer) set(CMAKE_CXX_STANDARD 17) -find_package(PkgConfig REQUIRED) -pkg_check_modules(TCPSocket REQUIRED TCPSocket) - add_executable(socketServer main.cpp - ModelecServer.cpp - ModelecServer.h) -target_link_libraries(socketServer TCPSocket) + TCPServer.cpp + TCPServer.h) diff --git a/ModelecServer.cpp b/ModelecServer.cpp deleted file mode 100644 index 3bc301f..0000000 --- a/ModelecServer.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "ModelecServer.h" - -void ModelecServer::acceptConnections() -{ - TCPServer::acceptConnections(); -} - -ModelecServer::~ModelecServer() -{ - this->stop(); -} - -ModelecServer::ModelecServer(int port) : TCPServer(port) -{ - -} - -void ModelecServer::handleMessage(const std::string& message, int clientSocket) -{ - std::cout << "REceived message" << std::endl; - /*if (startWith(message, "request robotPose")) - { - this->broadcastMessage("robotPos 25 24 23 2"); - } - else if (startWith(message, "pong")) - { - std::string name = split(message, " ")[1]; - std::cout << "Pong from " << name << std::endl; - } else - { - std::cout << message << std::endl; - }*/ -} diff --git a/ModelecServer.h b/ModelecServer.h deleted file mode 100644 index 5ae6cc0..0000000 --- a/ModelecServer.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -class ModelecServer : public TCPServer { - -public: - void acceptConnections() override; - - ~ModelecServer() override; - - explicit ModelecServer(int port); - - void handleMessage(const std::string& message, int clientSocket) override; -}; diff --git a/TCPServer.cpp b/TCPServer.cpp new file mode 100644 index 0000000..a3646e3 --- /dev/null +++ b/TCPServer.cpp @@ -0,0 +1,145 @@ +#include "TCPServer.h" + +ClientHandler::ClientHandler(int clientSocket, TCPServer* server) : clientSocket(clientSocket), server(server) {}; + +void ClientHandler::handle() { + std::string buffer; + buffer.reserve(4096); // Pre-allocate memory to avoid frequent allocations + + while (true) { + char tempBuffer[4096] = {0}; + ssize_t valread = recv(clientSocket, tempBuffer, sizeof(tempBuffer), 0); + + if (valread > 0) { + buffer.append(tempBuffer, valread); + //std::cout << "Received: " << buffer << std::endl; + + if (buffer == "quit") { + std::cout << "Client requested to quit. Closing connection." << std::endl; + break; + } + processMessage(buffer); + } else if (valread == 0) { + std::cout << "Client disconnected." << std::endl; + break; // Client disconnected + } else { + std::cerr << "Failed to receive data." << std::endl; + break; // Error in receiving data + } + } + + closeConnection(); +} + +void ClientHandler::processMessage(const std::string& message) { + server->handleMessage(message, clientSocket); +} + +void ClientHandler::closeConnection() { + close(clientSocket); + server->clientDisconnected(clientSocket); // Inform the server that the client has disconnected +} + +TCPServer::TCPServer(int port) +{ + serverSocket = socket(AF_INET, SOCK_STREAM, 0); + if (serverSocket == -1) { + std::cerr << "Socket creation failed" << std::endl; + exit(EXIT_FAILURE); + } + + sockaddr_in address{}; + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); + + if (bind(serverSocket, reinterpret_cast(&address), sizeof(address)) == -1) { + std::cerr << "Binding failed" << std::endl; + exit(EXIT_FAILURE); + } + + if (listen(serverSocket, 5) == -1) { + std::cerr << "Listening failed" << std::endl; + exit(EXIT_FAILURE); + } + + std::cout << "Server started on port " << port << std::endl; +} + +void TCPServer::acceptConnections() +{ + while (!shouldStop) { + sockaddr_in clientAddress{}; + int addrlen = sizeof(clientAddress); + int clientSocket = + accept(serverSocket, reinterpret_cast(&clientAddress), reinterpret_cast(&addrlen)); + if (clientSocket == -1) { + std::cerr << "Accepting connection failed" << std::endl; + continue; + } + std::cout << "Connection accepted" << std::endl; + + // Add the client socket to the list + clientSockets.push_back(clientSocket); + connectedClients++; + + // Handle client connection in a separate thread + clientThreads.emplace_back(&ClientHandler::handle, ClientHandler(clientSocket, this)); + // Clean up finished threads + clientThreads.erase(std::remove_if(clientThreads.begin(), clientThreads.end(), [](std::thread &t) { + return !t.joinable(); + }), clientThreads.end()); + } +} + + + +void TCPServer::handleMessage(const std::string& message, int clientSocket) +{ + std::cout << "Message from : " << clientSocket << " : " << message << std::endl; +} + + +void TCPServer::broadcastMessage(const char* message, int senderSocket) +{ + for (int clientSocket : clientSockets) { + if (clientSocket != senderSocket) { // Exclude the sender's socket + send(clientSocket, message, strlen(message), 0); + } + } +} + +void TCPServer::clientDisconnected(const int clientSocket) { + // Remove the disconnected client's socket + clientSockets.erase(std::remove(clientSockets.begin(), clientSockets.end(), clientSocket), clientSockets.end()); + // Decrement the count of connected clients + connectedClients--; +} + +void TCPServer::stop() { + shouldStop = true; + // Close all client sockets + for (int clientSocket : clientSockets) { + close(clientSocket); + } + // Close the server socket + close(serverSocket); +} + +TCPServer::~TCPServer() { + this->stop(); + // Join all threads before exiting + for (auto& thread : clientThreads) { + thread.join(); + } +} + +int TCPServer::nbClients() +{ + return connectedClients; +} + +void TCPServer::start() +{ + std::thread([this]() { acceptConnections(); }).detach(); +} diff --git a/TCPServer.h b/TCPServer.h new file mode 100644 index 0000000..bb03d94 --- /dev/null +++ b/TCPServer.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +class TCPServer; // Forward declaration + +class ClientHandler { +private: + int clientSocket; + TCPServer* server; // Reference to the TCPServer instance + +public: + explicit ClientHandler(int clientSocket, TCPServer* server); + + void handle(); + + void processMessage(const std::string& message); + + void closeConnection(); +}; + +class TCPServer { +private: + int serverSocket; + std::vector clientThreads; + std::vector clientSockets; // Store connected client sockets + int connectedClients = 0; // Track the number of connected clients + bool shouldStop = false; // Flag to indicate if the server should stop + +public: + explicit TCPServer(int port); + + void start(); + + void acceptConnections(); + + // Broadcast message to all connected clients + void broadcastMessage(const char* message, int senderSocket = -1); // Modified method signature + + void handleMessage(const std::string& message, int clientSocket); + + void clientDisconnected(int clientSocket); // New method to handle client disconnection + + void stop(); + + int nbClients(); + + ~TCPServer(); +}; diff --git a/main.cpp b/main.cpp index 2f2a643..73cc274 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include "TCPServer.h" std::atomic keepRunning(true);