From 0e3b79dc8815a7c5bf13d5f5f624acb4d9a51d2d Mon Sep 17 00:00:00 2001 From: ethanglide Date: Tue, 9 Jul 2024 15:04:47 -0400 Subject: [PATCH] Improve socket connection style Previously, a new socket was being opened and closed on every call. Now, there is one socket per client which is used continuously until the connection closes. --- cpp-console-game/main.cpp | 4 +-- eRPC/Client.cpp | 20 +++++---------- eRPC/Client.hpp | 3 --- eRPC/Server.cpp | 53 ++++++++++++++++++++++++++++----------- eRPC/Server.hpp | 7 +++++- 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/cpp-console-game/main.cpp b/cpp-console-game/main.cpp index 86f039c..2e10423 100644 --- a/cpp-console-game/main.cpp +++ b/cpp-console-game/main.cpp @@ -72,7 +72,7 @@ std::pair echo(std::vector args) std::cout << std::endl; - return {true, "Echo Successful"}; + return {true, ""}; } int main(int argc, char **argv) @@ -101,7 +101,7 @@ int main(int argc, char **argv) client.call("echo", {"Hello", "World"}); client.call("movePlayer", {"1", "5", "5"}); client.call("movePlayer", {"1", "6", "6"}); - auto ret = client.call("echol", {"Goodbye", "World"}); + auto ret = client.call("echo", {"Goodbye", "World"}); std::cout << "Result: " << ret << std::endl; } diff --git a/eRPC/Client.cpp b/eRPC/Client.cpp index 542b929..6ac7f47 100644 --- a/eRPC/Client.cpp +++ b/eRPC/Client.cpp @@ -6,7 +6,6 @@ #include #include #include -#include int msgIdCounter = 0; @@ -24,15 +23,7 @@ namespace eRPC } this->serverAddress = serverAddress; - } - Client::~Client() - { - closeConnection(); - } - - void Client::openConnection() - { if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { throw std::runtime_error("Failed to create socket"); @@ -44,16 +35,19 @@ namespace eRPC } } - void Client::closeConnection() + Client::~Client() { + Request request(msgIdCounter++, "disconnect", {}); + + auto serialized = request.serialize(); + write(sockfd, serialized.c_str(), serialized.size() + 1); + close(sockfd); sockfd = -1; } std::string Client::call(std::string method, std::vector params) { - Client::openConnection(); - Request request(msgIdCounter++, method, params); auto serialized = request.serialize(); write(sockfd, serialized.c_str(), serialized.size() + 1); @@ -61,8 +55,6 @@ namespace eRPC char buffer[1024] = {0}; read(sockfd, buffer, 1024); - Client::closeConnection(); - Response response(buffer); if (!response.isOk()) diff --git a/eRPC/Client.hpp b/eRPC/Client.hpp index 9b4d2ff..bcbd5e2 100644 --- a/eRPC/Client.hpp +++ b/eRPC/Client.hpp @@ -17,9 +17,6 @@ namespace eRPC private: int sockfd; sockaddr_in serverAddress; - - void openConnection(); - void closeConnection(); }; } diff --git a/eRPC/Server.cpp b/eRPC/Server.cpp index 32cd4e6..c707905 100644 --- a/eRPC/Server.cpp +++ b/eRPC/Server.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace eRPC { @@ -50,11 +51,47 @@ namespace eRPC while (running) { auto connfd = accept(sockfd, (sockaddr *)NULL, NULL); + if (connfd < 0) + { + throw std::runtime_error("Failed to accept connection"); + } + // Start a new thread to serve the client + std::thread(&Server::serveClient, this, connfd).detach(); + } + + close(sockfd); + } + + void Server::stop() + { + running = false; + } + + void Server::bindMethod(std::string method, std::function(std::vector)> callback) + { + methods[method] = callback; + } + + void Server::serveClient(int connfd) + { + while (true) + { char buffer[1024] = {0}; - read(connfd, buffer, 1024); + if (read(connfd, buffer, 1024) <= 0) + { + break; + } + + // Parse the request Request request(buffer); + if (request.getMethod() == "disconnect") + { + break; + } + + // Call the method if it exists to generate a response std::unique_ptr response; if (methods.find(request.getMethod()) != methods.end()) { @@ -76,20 +113,8 @@ namespace eRPC auto serialized = response->serialize(); write(connfd, serialized.c_str(), serialized.size() + 1); - - close(connfd); } - close(sockfd); - } - - void Server::stop() - { - running = false; - } - - void Server::bindMethod(std::string method, std::function(std::vector)> callback) - { - methods[method] = callback; + close(connfd); } } \ No newline at end of file diff --git a/eRPC/Server.hpp b/eRPC/Server.hpp index d3a6858..0e5b2bd 100644 --- a/eRPC/Server.hpp +++ b/eRPC/Server.hpp @@ -21,7 +21,7 @@ namespace eRPC ~Server(); /** - * Start the server loop. + * Start the server loop. This will block until the server is stopped. */ void start(); @@ -39,6 +39,11 @@ namespace eRPC int sockfd; bool running; std::unordered_map(std::vector)>> methods; + + /** + * Keep a socket open and serve a client until they disconnect. + */ + void serveClient(int connfd); }; }