From 7d11e80bb3bd6fe9c2b8706b08b723ada674c687 Mon Sep 17 00:00:00 2001 From: ackimixs Date: Thu, 28 Mar 2024 08:24:50 +0100 Subject: [PATCH] change to TCP Client --- CMakeLists.txt | 25 +++----- MainWindow.h | 50 +++++++-------- main.cpp | 57 +++-------------- tcp/CMakeLists.txt | 9 --- tcp/TCPServer.cpp | 149 --------------------------------------------- tcp/TCPServer.hpp | 61 ------------------- tcp/main.cpp | 36 ----------- tcp/utils.hpp | 38 ------------ 8 files changed, 42 insertions(+), 383 deletions(-) delete mode 100644 tcp/CMakeLists.txt delete mode 100644 tcp/TCPServer.cpp delete mode 100644 tcp/TCPServer.hpp delete mode 100644 tcp/main.cpp delete mode 100644 tcp/utils.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d7e8066..afaa1e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,14 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) +find_package(PkgConfig REQUIRED) +pkg_check_modules(TCPSocket REQUIRED TCPSocket) + +find_package(Qt6 COMPONENTS + Core + Gui + Widgets + REQUIRED) set(HEADERS MainWindow.h @@ -36,26 +44,13 @@ set(SOURCES preparation/TiretteState.cpp ) -set(TCP - tcp/TCPServer.hpp - tcp/TCPServer.cpp - tcp/utils.hpp -) +add_executable(ihm_robot resource.qrc ${HEADERS} ${SOURCES}) - -find_package(Qt6 COMPONENTS - Core - Gui - Widgets - Network - REQUIRED) - -add_executable(ihm_robot resource.qrc ${HEADERS} ${SOURCES} ${TCP}) +target_link_libraries(ihm_robot TCPSocket) target_link_libraries(ihm_robot Qt::Core Qt::Gui Qt::Widgets - Qt::Network ) diff --git a/MainWindow.h b/MainWindow.h index 069341b..ece87ce 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "homeButton.h" #include "Homologation.h" @@ -12,10 +14,10 @@ #include "TeamChooser.h" #include "TestMode.h" -class MainWindow : public QMainWindow { +class MainWindow : public QMainWindow, public TCPClient { Q_OBJECT public: - MainWindow(QWidget* parent = nullptr) : QMainWindow(parent) + MainWindow(const char* address = "127.0.0.1", int port = 8080, QWidget* parent = nullptr) : QMainWindow(parent), TCPClient(address, port) { this->centralWidget = new QWidget(this); this->setCentralWidget(centralWidget); @@ -65,7 +67,9 @@ public: this->preparationMatch = new PreparationMatch(centralWidget); connect(this->preparationMatch, &PreparationMatch::startGame, this, &MainWindow::onStartGame); // connect(this->preparationMatch, &PreparationMatch::askTCPServer, this, &MainWindow::broadcastTCPMessage); - connect(this->preparationMatch, &PreparationMatch::askTCPServer, this, &MainWindow::broadcastTCPMessage); + connect(this->preparationMatch, &PreparationMatch::askTCPServer, [&](const std::string& message) { + this->sendMessage(message.c_str()); + }); this->testMode = new TestMode(centralWidget); connect(this->testMode, &TestMode::goPressed, this, &MainWindow::moveRobot); @@ -105,6 +109,24 @@ public: this->stackedWidget->setCurrentIndex(index); } + void handleMessage(const std::string& message) override + { + std::vector list = split(message, ";"); + + if (startWith(list[2], "pong")) + { + preparationMatch->responseFromPing(QString::fromStdString(message)); + } + if (contains(list[0], "tirette") && contains(list[2], "set state")) + { + preparationMatch->responseTiretteState(QString::fromStdString(message)); + } + if (contains(list[0], "lidar")) + { + preparationMatch->responseLidar(QString::fromStdString(message)); + } + } + protected slots: void onHomePressed() { @@ -146,32 +168,10 @@ protected slots: emit replierRobot(); } -public slots: - void onTCPMesssageReceived(const std::string& message) - { - QString qMessage = QString::fromStdString(message); - - auto list = qMessage.split(";"); - - if (list[2].startsWith("pong")) - { - preparationMatch->responseFromPing(qMessage); - } - if (list[0] == "tirette" && list[2] == "set state") - { - preparationMatch->responseTiretteState(qMessage); - } - if (list[0] == "lidar") - { - preparationMatch->responseLidar(qMessage); - } - } - signals: void deplierRobot(); void replierRobot(); void moveRobot(int x, int y, int theta); - void broadcastTCPMessage(const std::string& message); private: QVBoxLayout* mainLayout; diff --git a/main.cpp b/main.cpp index d92a524..328bf60 100644 --- a/main.cpp +++ b/main.cpp @@ -4,12 +4,17 @@ #include #include "MainWindow.h" -#include "tcp/TCPServer.hpp" int main(int argc, char* argv[]) { QApplication a(argc, argv); - auto* main = new MainWindow; + int port = 8080; + if (argc >= 3) + { + port = std::stoi(argv[2]); + } + + auto* main = new MainWindow("127.0.0.1", port); MainWindow::connect(main, &MainWindow::replierRobot, [=]() { @@ -40,53 +45,5 @@ int main(int argc, char* argv[]) { main->show(); } - int port = 8080; - if (argc == 3) - { - port = std::stoi(argv[2]); - } - - auto* server = new TCPServer(port); - server->start(); - - QObject::connect(server, &TCPServer::messageReceived, main, &MainWindow::onTCPMesssageReceived); - QObject::connect(main, &MainWindow::broadcastTCPMessage, [server](const std::string& message) - { - server->broadcastMessage(message.c_str()); - }); - - // Create a new thread for the server - QThread serverThread; - server->moveToThread(&serverThread); - serverThread.start(); - - // Create a lambda function to run the while loop - auto runServerLoop = [&]() { - while (true) { - std::string message; - std::cout << "Enter message ('quit' to exit): "; - std::getline(std::cin, message); - - if (message == "quit") { - // Stop the server and exit the loop - server->stop(); - break; - } - - // Broadcast the message from the server - server->broadcastMessage(message.c_str()); - } - }; - - // Move the lambda function to the new thread - QObject::connect(&serverThread, &QThread::started, runServerLoop); - - // Connect aboutToQuit signal to stop the thread and wait for it to finish - QObject::connect(&a, &QCoreApplication::aboutToQuit, [&]() { - server->stop(); // Stop the server - serverThread.quit(); // Quit the thread event loop - serverThread.wait(); // Wait for the thread to finish - }); - return QApplication::exec(); } diff --git a/tcp/CMakeLists.txt b/tcp/CMakeLists.txt deleted file mode 100644 index 8aa99ba..0000000 --- a/tcp/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.25) -project(socketServer) - -set(CMAKE_CXX_STANDARD 17) - -add_executable(socketServer main.cpp - TCPServer.cpp - TCPServer.hpp - utils.hpp) diff --git a/tcp/TCPServer.cpp b/tcp/TCPServer.cpp deleted file mode 100644 index 094de89..0000000 --- a/tcp/TCPServer.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "TCPServer.hpp" - -#include "utils.hpp" - -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); - - buffer.clear(); - } 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, QObject* parent) : QObject(parent) -{ - 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) -{ - emit messageReceived(message, clientSocket); -} - - -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/tcp/TCPServer.hpp b/tcp/TCPServer.hpp deleted file mode 100644 index 7ac6833..0000000 --- a/tcp/TCPServer.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#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 : public QObject { - Q_OBJECT - - 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, QObject* parent = nullptr); - - 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 = -1); - - void clientDisconnected(int clientSocket); // New method to handle client disconnection - - void stop(); - - int nbClients(); - - ~TCPServer(); - -signals: - void messageReceived(const std::string& message, int clientSocket); -}; diff --git a/tcp/main.cpp b/tcp/main.cpp deleted file mode 100644 index 88f8dd3..0000000 --- a/tcp/main.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "TCPServer.hpp" - -std::atomic keepRunning(true); - -void signalHandler(int signum) { - std::cout << "Interrupt signal (" << signum << ") received.\n"; - keepRunning = false; -} - -int main() { - signal(SIGTERM, signalHandler); - signal(SIGINT, signalHandler); - - TCPServer server(8080); - - try { - server.start(); - - while (keepRunning) { - sleep(1); - - server.broadcastMessage("request aruco"); - - std::cout << "Main thread communicating with server..." << std::endl; - } - - server.stop(); - } catch (const std::exception& ex) { - std::cerr << "Error: " << ex.what() << std::endl; - return 1; - } - return 0; -} \ No newline at end of file diff --git a/tcp/utils.hpp b/tcp/utils.hpp deleted file mode 100644 index 5f19d04..0000000 --- a/tcp/utils.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include - -inline bool startWith(const std::string& str, const std::string& start) -{ - return str.rfind(start, 0) == 0; -} - -inline bool endsWith(const std::string& str, const std::string& end) -{ - if (str.length() >= end.length()) - { - return (0 == str.compare(str.length() - end.length(), end.length(), end)); - } - return false; -} - -inline bool contains(const std::string& str, const std::string& sub) -{ - return str.find(sub) != std::string::npos; -} - -inline std::vector split(const std::string& str, const std::string& delimiter) -{ - std::vector tokens; - size_t prev = 0, pos = 0; - do - { - pos = str.find(delimiter, prev); - if (pos == std::string::npos) pos = str.length(); - std::string token = str.substr(prev, pos - prev); - if (!token.empty()) tokens.push_back(token); - prev = pos + delimiter.length(); - } while (pos < str.length() && prev < str.length()); - return tokens; -} \ No newline at end of file