From 8a97a328239566e892cc76d202df775e1103c7b3 Mon Sep 17 00:00:00 2001 From: Blitblank Date: Tue, 21 Jul 2026 21:29:29 -0500 Subject: [PATCH] fix server broadcasting demo --- README.md | 4 +-- client/src/TcpClient.cpp | 69 ++++++++++++++++++++++++---------------- client/src/TcpClient.hpp | 5 +++ server/src/TcpServer.cpp | 7 ++-- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index cf8c68c..0337b0c 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ An Accordion server allows clients to view and publish chat messages; authentica Total running list of external software source packages: - OpenSSL: TLS Networking Security - - RtMidi: Realtime Audio I/O Processing + - RtAudio: Realtime Audio I/O Processing - libconfig++: Configuration File Interfacing - more to come in the future 🐰 Similarly, a list of dependent linux packages: @@ -27,7 +27,7 @@ Similarly, a list of dependent linux packages: ## Development plan: - [x] Build & project setup, get working hello-world program. -- [ ] TCP Demo between client and server +- [x] TCP Demo between client and server - [ ] Add TLS with OpenSSL on top of the TCP - [ ] Build and deploy server to a Docker container in a CI/CD pipeline - [ ] Implement PostgreSQL interfacing for the server diff --git a/client/src/TcpClient.cpp b/client/src/TcpClient.cpp index 370cc0c..c3c42ff 100644 --- a/client/src/TcpClient.cpp +++ b/client/src/TcpClient.cpp @@ -24,27 +24,25 @@ ErrorCode TcpClient::init() { logger_->log("TcpClient", LogFlag::Debug, "Initializing TcpClient..."); // keeping everything in here for now - int socketFd; // file descriptor for the client socket (socket proper is a function) - int sendBytes; int receiveBytes; char buffer[1024]; struct hostent* host; // houses host network info - struct sockaddr_in serverAddress; // ip address of the server socket + struct sockaddr_in serverAddress; // ip address of the server socket // parse the hostname string into uint8s host = gethostbyname(configuration_.hostname.c_str()); if(host == NULL) { logger_->log("TcpClient", LogFlag::Debug, "Unable to parse hostname."); - close(socketFd); // TODO: probably on a destructor + close(socketFd_); // TODO: probably on a destructor return ErrorCode::Error; } // create tcp socket - socketFd = socket(AF_INET, SOCK_STREAM, 0); - if(socketFd < 0) { + socketFd_ = socket(AF_INET, SOCK_STREAM, 0); + if(socketFd_ < 0) { logger_->log("TcpClient", LogFlag::Debug, "Unable to open client socket."); - close(socketFd); + close(socketFd_); return ErrorCode::Error; } @@ -55,31 +53,25 @@ ErrorCode TcpClient::init() { serverAddress.sin_addr = *((struct in_addr*)host->h_addr); // connect to server - if(connect(socketFd, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) { + if(connect(socketFd_, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr)) < 0) { logger_->log("TcpClient", LogFlag::Debug, "Unable to connect to server."); - close(socketFd); + close(socketFd_); return ErrorCode::Error; } - std::string message = "placeholder"; - while(!message.empty()) { - logger_->log("TcpClient", LogFlag::Debug, "Enter message..."); - std::getline(std::cin, message); - - // send data buffer to server - sendBytes = tcpSend(socketFd, message.c_str(), message.size()); - - if(sendBytes < 0) { - logger_->log("TcpClient", LogFlag::Error, "Unable to send to server."); - close(socketFd); - return ErrorCode::Error; - } - logger_->log("TcpClient", LogFlag::Debug, "Sent {} bytes to the server.", sendBytes); - + // start sending thread (only needed for cli because std::cin is blocking. a regular message box doesn't need to block for input) + pthread_t messengerThread; + if(pthread_create(&messengerThread, NULL, TcpClient::sendMessage, static_cast(this)) != 0) { + logger_->log("TcpClient", LogFlag::Debug, "Unable to spawn messenger thread."); + close(socketFd_); + return ErrorCode::Error; + } + + while(true) { // listen for receive from the server memset(buffer, 0x00, sizeof(buffer)); - receiveBytes = tcpRead(socketFd, buffer, sizeof(buffer)); // TODO: this currently blocks forever, add timeout + receiveBytes = tcpRead(socketFd_, buffer, sizeof(buffer)); // TODO: this currently blocks forever, add timeout // TODO: separate thread // we expect a response based on the server design, something went wrong otherwise @@ -88,7 +80,7 @@ ErrorCode TcpClient::init() { return ErrorCode::Error; } else if(receiveBytes == 0) { logger_->log("TcpClient", LogFlag::Error, "Server closed the connection during receive."); - close(socketFd); + close(socketFd_); return ErrorCode::Error; } @@ -96,7 +88,30 @@ ErrorCode TcpClient::init() { logger_->log("TcpClient", LogFlag::Debug, "Received {} bytes back from the server: {}", receiveBytes, receivedMessage); } - close(socketFd); + close(socketFd_); + pthread_join(messengerThread, NULL); return ErrorCode::Success; } + +void* TcpClient::sendMessage(void* arg) { + + int sendBytes; + std::string message = "placeholder"; + TcpClient* obj = static_cast(arg); + + while(true) { + obj->logger_->log("TcpClient", LogFlag::Debug, "Enter message..."); + std::getline(std::cin, message); + + // send data buffer to server + sendBytes = obj->tcpSend(obj->socketFd_, message.c_str(), message.size()); + + if(sendBytes < 0) { + obj->logger_->log("TcpClient", LogFlag::Error, "Unable to send to server."); + close(obj->socketFd_); + return nullptr; + } + obj->logger_->log("TcpClient", LogFlag::Debug, "Sent {} bytes to the server.", sendBytes); + } +} diff --git a/client/src/TcpClient.hpp b/client/src/TcpClient.hpp index bd1dc0f..262f944 100644 --- a/client/src/TcpClient.hpp +++ b/client/src/TcpClient.hpp @@ -7,6 +7,7 @@ #include #include #include // TODO replace with chrono +#include #include "common/config/ConfigService.hpp" #include "common/LoggerService.hpp" @@ -25,6 +26,10 @@ private: ErrorCode init(); + // handler for sending messages since std::cin is blocking + static void* sendMessage(void* arg); + ClientParams configuration_; + int socketFd_; // file descriptor for the client socket (socket proper is a function) }; diff --git a/server/src/TcpServer.cpp b/server/src/TcpServer.cpp index 7c01d61..9742a11 100644 --- a/server/src/TcpServer.cpp +++ b/server/src/TcpServer.cpp @@ -172,8 +172,10 @@ ErrorCode TcpServer::handleMessage(const char* message, size_t msgLength, uint32 logger_->log("TcpClient", LogFlag::Debug, "Received {} bytes from client {}: {}", msgLength, clientAddresses[socketId], messageString); + messageString = std::format("{}: {}", clientAddresses[socketId], messageString); + // broadcast to all clients - if(broadcastMessage(message, msgLength) != ErrorCode::Success) { + if(broadcastMessage(messageString.c_str(), messageString.length()) != ErrorCode::Success) { logger_->log("TcpServer", LogFlag::Error, "Broadcast failure."); return ErrorCode::Error; } @@ -183,7 +185,8 @@ ErrorCode TcpServer::handleMessage(const char* message, size_t msgLength, uint32 ErrorCode TcpServer::broadcastMessage(const char* message, size_t msgLength) { - for(size_t i = 1; i < clientCount; i++) { + for(size_t i = 1; i <= clientCount; i++) { + if(sockets[i].fd == -1) continue; ssize_t sendBytes = tcpSend(sockets[i].fd, message, msgLength); if(sendBytes != msgLength) {