mirror of
https://github.com/kierankihn/uno-game.git
synced 2025-12-27 02:13:18 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
68
src/network/Session.cpp
Normal 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
43
src/network/Session.h
Normal 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
|
||||
Reference in New Issue
Block a user