mirror of
https://github.com/modelec/TCPSocketServer.git
synced 2026-01-18 16:37:29 +01:00
Omg v4 ?
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}*/
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <TCPSocket/TCPServer.hpp>
|
||||
|
||||
class ModelecServer : public TCPServer {
|
||||
|
||||
public:
|
||||
void acceptConnections() override;
|
||||
|
||||
~ModelecServer() override;
|
||||
|
||||
explicit ModelecServer(int port);
|
||||
|
||||
void handleMessage(const std::string& message, int clientSocket) override;
|
||||
};
|
||||
145
TCPServer.cpp
Normal file
145
TCPServer.cpp
Normal file
@@ -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<struct sockaddr*>(&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<struct sockaddr*>(&clientAddress), reinterpret_cast<socklen_t*>(&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();
|
||||
}
|
||||
56
TCPServer.h
Normal file
56
TCPServer.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
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<std::thread> clientThreads;
|
||||
std::vector<int> 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();
|
||||
};
|
||||
Reference in New Issue
Block a user