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.
This commit is contained in:
Kieran Kihn
2025-12-04 14:42:22 +08:00
parent 7363556ad5
commit 1d2e77aca3
6 changed files with 128 additions and 109 deletions

View File

@@ -7,42 +7,26 @@
#include "NetworkClient.h"
#include <asio/connect.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>
#include <memory>
#include <utility>
namespace UNO::NETWORK {
NetworkClient::NetworkClient(std::function<void(std::string)> callback) : socket_(io_context_), callback_(std::move(callback)) {}
NetworkClient::NetworkClient(std::function<void(std::string)> 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<Session>(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<char> buffer(length);
asio::read(this->socket_, asio::buffer(buffer));
return {buffer.begin(), buffer.end()};
this->session_->send(message);
}
} // namespace UNO::NETWORK

View File

@@ -5,17 +5,19 @@
* @date 2025.11.28
*/
#pragma once
#include "Session.h"
#include <asio/io_context.hpp>
#include <asio/ip/tcp.hpp>
namespace UNO::NETWORK {
class NetworkClient {
private:
asio::io_context io_context_;
asio::ip::tcp::socket socket_;
std::function<void(std::string)> callback_;
std::shared_ptr<Session> session_;
public:
explicit NetworkClient(std::function<void(std::string)> 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

View File

@@ -9,52 +9,6 @@
#include <utility>
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<void(size_t, std::string)> callback)
{
this->callback_ = std::move(callback);
read();
}
void Session::send(const std::string &message)
{
auto length = std::make_shared<size_t>(message.size());
auto msg = std::make_shared<std::string>(message);
std::array<asio::const_buffer, 2> 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<size_t>(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<std::vector<char>>(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<std::mutex> lock(this->mutex_);
this->sessions_[this->playerCount] = std::make_shared<Session>(playerCount, std::move(socket));
this->sessions_[this->playerCount]->start(callback_);
size_t playerId = this->playerCount;
this->sessions_[playerId] = std::make_shared<Session>(std::move(socket));
this->sessions_[playerId]->start([this, playerId](std::string message) { this->callback_(playerId, std::move(message)); });
this->playerCount++;
}

View File

@@ -5,8 +5,8 @@
* @date 2025.11.25
*/
#pragma once
#include "Message.h"
#include "Session.h"
#include <asio.hpp>
#include <map>
@@ -14,32 +14,6 @@
namespace UNO::NETWORK {
class Session : public std::enable_shared_from_this<Session> {
private:
size_t player_id_;
asio::ip::tcp::socket socket_;
std::function<void(size_t, std::string)> callback_;
public:
Session(size_t player_id, asio::ip::tcp::socket socket);
/**
* 开始从网络读取消息
* @param callback 回调函数
*/
void start(std::function<void(size_t, std::string)> 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_;

68
src/network/Session.cpp Normal file
View File

@@ -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<void(std::string)> 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<size_t>(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<std::vector<char>>(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<size_t>(message.size());
auto msg = std::make_shared<std::string>(message);
std::array<asio::const_buffer, 2> 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

43
src/network/Session.h Normal file
View File

@@ -0,0 +1,43 @@
/**
* @file Session.h
*
* @author Yuzhe Guo
* @date 2025.12.04
*/
#pragma once
#include <asio.hpp>
#include <memory>
#include <queue>
namespace UNO::NETWORK {
class Session : public std::enable_shared_from_this<Session> {
private:
asio::ip::tcp::socket socket_;
std::function<void(std::string)> callback_;
std::queue<std::string> messages_;
public:
explicit Session(asio::ip::tcp::socket socket);
/**
* 开始从网络读取消息
* @param callback 回调函数
*/
void start(std::function<void(std::string)> callback);
/**
* 发送消息
* @param message 要发送的消息
*/
void send(const std::string &message);
private:
void doRead();
void doReadBody(size_t length);
void doWrite();
};
} // namespace UNO::NETWORK