From 1d2e77aca3a1a74f97edf85c96d5656c798ae21e Mon Sep 17 00:00:00 2001 From: Kieran Kihn <114803508+kierankihn@users.noreply.github.com> Date: Thu, 4 Dec 2025 14:42:22 +0800 Subject: [PATCH] refactor(network): integrate `NetworkClient` with `Session` - Moved `Session` implementation to `Session.cpp` and `Session.h`. - Updated `Session` to use a `message` queue for sending data, improving handling of writes. - Adjusted `NetworkClient` and `NetworkServer` to integrate with the new `Session` logic. --- src/network/NetworkClient.cpp | 32 +++++------------ src/network/NetworkClient.h | 15 +++----- src/network/NetworkServer.cpp | 51 ++------------------------ src/network/NetworkServer.h | 28 +-------------- src/network/Session.cpp | 68 +++++++++++++++++++++++++++++++++++ src/network/Session.h | 43 ++++++++++++++++++++++ 6 files changed, 128 insertions(+), 109 deletions(-) create mode 100644 src/network/Session.cpp create mode 100644 src/network/Session.h diff --git a/src/network/NetworkClient.cpp b/src/network/NetworkClient.cpp index 51160a4..00dafb0 100644 --- a/src/network/NetworkClient.cpp +++ b/src/network/NetworkClient.cpp @@ -7,42 +7,26 @@ #include "NetworkClient.h" #include -#include -#include +#include #include namespace UNO::NETWORK { - NetworkClient::NetworkClient(std::function callback) : socket_(io_context_), callback_(std::move(callback)) {} + NetworkClient::NetworkClient(std::function callback) : callback_(std::move(callback)) {} void NetworkClient::connect(const std::string &host, uint16_t port) { - this->disconnect(); + asio::ip::tcp::socket socket(io_context_); + asio::ip::tcp::resolver resolver(io_context_); auto endpoints = resolver.resolve(host, std::to_string(port)); - asio::connect(socket_, endpoints.begin(), endpoints.end()); - } - void NetworkClient::disconnect() - { - if (socket_.is_open()) { - this->socket_.close(); - } + this->session_ = std::make_shared(std::move(socket)); + this->session_->start(callback_); } - void NetworkClient::send(const std::string &message) + void NetworkClient::send(const std::string &message) const { - size_t length = message.size(); - asio::write(this->socket_, asio::buffer(&length, sizeof(length))); - asio::write(this->socket_, asio::buffer(message)); - } - - std::string NetworkClient::read() - { - size_t length; - asio::read(this->socket_, asio::buffer(&length, sizeof(length))); - std::vector buffer(length); - asio::read(this->socket_, asio::buffer(buffer)); - return {buffer.begin(), buffer.end()}; + this->session_->send(message); } } // namespace UNO::NETWORK diff --git a/src/network/NetworkClient.h b/src/network/NetworkClient.h index c37a918..eeedca9 100644 --- a/src/network/NetworkClient.h +++ b/src/network/NetworkClient.h @@ -5,17 +5,19 @@ * @date 2025.11.28 */ #pragma once +#include "Session.h" + #include -#include namespace UNO::NETWORK { class NetworkClient { private: asio::io_context io_context_; - asio::ip::tcp::socket socket_; std::function callback_; + std::shared_ptr session_; + public: explicit NetworkClient(std::function callback); @@ -26,18 +28,11 @@ namespace UNO::NETWORK { */ void connect(const std::string &host, uint16_t port); - /** - * 关闭到服务端的连接 - */ - void disconnect(); - /** * 向服务端发送消息 * @param message 要发送的消息 */ - void send(const std::string &message); - - [[nodiscard]] std::string read(); + void send(const std::string &message) const; }; } // namespace UNO::NETWORK diff --git a/src/network/NetworkServer.cpp b/src/network/NetworkServer.cpp index 06e402c..e8eb714 100644 --- a/src/network/NetworkServer.cpp +++ b/src/network/NetworkServer.cpp @@ -9,52 +9,6 @@ #include namespace UNO::NETWORK { - Session::Session(size_t player_id, asio::ip::tcp::socket socket) : player_id_(player_id), socket_(std::move(socket)) {} - - void Session::start(std::function callback) - { - this->callback_ = std::move(callback); - read(); - } - - void Session::send(const std::string &message) - { - auto length = std::make_shared(message.size()); - auto msg = std::make_shared(message); - std::array buffers = {asio::buffer(length.get(), sizeof(size_t)), asio::buffer(*msg)}; - asio::async_write(socket_, buffers, [this, self = shared_from_this(), length, msg](const asio::error_code &ec, size_t) {}); - } - - void Session::read() - { - auto messageLength = std::make_shared(0); - asio::async_read(socket_, - asio::buffer(messageLength.get(), sizeof(size_t)), - [this, self = shared_from_this(), messageLength](const asio::error_code &ec, size_t length) { - if (!ec) { - if (*messageLength <= 10 * 1024 * 1024) { - this->readBody(*messageLength); - } - else { - read(); - } - } - }); - } - - void Session::readBody(size_t length) - { - auto buffer = std::make_shared>(length); - asio::async_read( - socket_, asio::buffer(*buffer), [this, self = shared_from_this(), buffer](const asio::error_code &ec, size_t length) { - if (!ec) { - std::string message = {buffer->begin(), buffer->end()}; - this->callback_(this->player_id_, message); - read(); - } - }); - } - void NetworkServer::accept() { this->acceptor_.async_accept([this](const asio::error_code &ec, asio::ip::tcp::socket socket) { @@ -74,8 +28,9 @@ namespace UNO::NETWORK { void NetworkServer::addPlayer(asio::ip::tcp::socket socket) { std::lock_guard lock(this->mutex_); - this->sessions_[this->playerCount] = std::make_shared(playerCount, std::move(socket)); - this->sessions_[this->playerCount]->start(callback_); + size_t playerId = this->playerCount; + this->sessions_[playerId] = std::make_shared(std::move(socket)); + this->sessions_[playerId]->start([this, playerId](std::string message) { this->callback_(playerId, std::move(message)); }); this->playerCount++; } diff --git a/src/network/NetworkServer.h b/src/network/NetworkServer.h index 961a13c..210d442 100644 --- a/src/network/NetworkServer.h +++ b/src/network/NetworkServer.h @@ -5,8 +5,8 @@ * @date 2025.11.25 */ #pragma once -#include "Message.h" +#include "Session.h" #include #include @@ -14,32 +14,6 @@ namespace UNO::NETWORK { - class Session : public std::enable_shared_from_this { - private: - size_t player_id_; - asio::ip::tcp::socket socket_; - std::function callback_; - - public: - Session(size_t player_id, asio::ip::tcp::socket socket); - - /** - * 开始从网络读取消息 - * @param callback 回调函数 - */ - void start(std::function callback); - - /** - * 发送消息 - * @param message 要发送的消息 - */ - void send(const std::string &message); - - private: - void read(); - void readBody(size_t length); - }; - class NetworkServer { private: asio::io_context io_context_; diff --git a/src/network/Session.cpp b/src/network/Session.cpp new file mode 100644 index 0000000..19414f3 --- /dev/null +++ b/src/network/Session.cpp @@ -0,0 +1,68 @@ +/** + * @file Session.cpp + * + * @author Yuzhe Guo + * @date 2025.12.04 + */ +#include "Session.h" + +namespace UNO::NETWORK { + Session::Session(asio::ip::tcp::socket socket) : socket_(std::move(socket)) {} + + void Session::start(std::function callback) + { + this->callback_ = std::move(callback); + this->doRead(); + } + + void Session::send(const std::string &message) + { + bool writeInProgress = !this->messages_.empty(); + messages_.push(message); + if (writeInProgress == false) { + this->doWrite(); + } + } + + void Session::doRead() + { + auto messageLength = std::make_shared(0); + asio::async_read(socket_, + asio::buffer(messageLength.get(), sizeof(size_t)), + [this, self = shared_from_this(), messageLength](const asio::error_code &ec, size_t length) { + if (!ec) { + if (*messageLength <= 10 * 1024 * 1024) { + this->doReadBody(*messageLength); + } + else { + doRead(); + } + } + }); + } + + void Session::doReadBody(size_t length) + { + auto buffer = std::make_shared>(length); + asio::async_read( + socket_, asio::buffer(*buffer), [this, self = shared_from_this(), buffer](const asio::error_code &ec, size_t length) { + if (!ec) { + std::string message = {buffer->begin(), buffer->end()}; + this->callback_(message); + doRead(); + } + }); + } + + void Session::doWrite() + { + auto message = this->messages_.front(); + this->messages_.pop(); + + auto length = std::make_shared(message.size()); + auto msg = std::make_shared(message); + + std::array buffers = {asio::buffer(length.get(), sizeof(size_t)), asio::buffer(*msg)}; + asio::async_write(socket_, buffers, [this, self = shared_from_this(), length, msg](const asio::error_code &ec, size_t) {}); + } +} // namespace UNO::NETWORK \ No newline at end of file diff --git a/src/network/Session.h b/src/network/Session.h new file mode 100644 index 0000000..d178306 --- /dev/null +++ b/src/network/Session.h @@ -0,0 +1,43 @@ +/** + * @file Session.h + * + * @author Yuzhe Guo + * @date 2025.12.04 + */ +#pragma once + +#include +#include +#include + +namespace UNO::NETWORK { + + class Session : public std::enable_shared_from_this { + private: + asio::ip::tcp::socket socket_; + std::function callback_; + + std::queue messages_; + + public: + explicit Session(asio::ip::tcp::socket socket); + + /** + * 开始从网络读取消息 + * @param callback 回调函数 + */ + void start(std::function callback); + + /** + * 发送消息 + * @param message 要发送的消息 + */ + void send(const std::string &message); + + private: + void doRead(); + void doReadBody(size_t length); + void doWrite(); + }; + +} // namespace UNO::NETWORK \ No newline at end of file