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 "NetworkClient.h"
|
||||||
|
|
||||||
#include <asio/connect.hpp>
|
#include <asio/connect.hpp>
|
||||||
#include <asio/read.hpp>
|
#include <memory>
|
||||||
#include <asio/write.hpp>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace UNO::NETWORK {
|
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)
|
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_);
|
asio::ip::tcp::resolver resolver(io_context_);
|
||||||
auto endpoints = resolver.resolve(host, std::to_string(port));
|
auto endpoints = resolver.resolve(host, std::to_string(port));
|
||||||
asio::connect(socket_, endpoints.begin(), endpoints.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkClient::disconnect()
|
this->session_ = std::make_shared<Session>(std::move(socket));
|
||||||
{
|
this->session_->start(callback_);
|
||||||
if (socket_.is_open()) {
|
|
||||||
this->socket_.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NetworkClient::send(const std::string &message)
|
void NetworkClient::send(const std::string &message) const
|
||||||
{
|
{
|
||||||
size_t length = message.size();
|
this->session_->send(message);
|
||||||
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()};
|
|
||||||
}
|
}
|
||||||
} // namespace UNO::NETWORK
|
} // namespace UNO::NETWORK
|
||||||
|
|||||||
@@ -5,17 +5,19 @@
|
|||||||
* @date 2025.11.28
|
* @date 2025.11.28
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Session.h"
|
||||||
|
|
||||||
#include <asio/io_context.hpp>
|
#include <asio/io_context.hpp>
|
||||||
#include <asio/ip/tcp.hpp>
|
|
||||||
|
|
||||||
namespace UNO::NETWORK {
|
namespace UNO::NETWORK {
|
||||||
|
|
||||||
class NetworkClient {
|
class NetworkClient {
|
||||||
private:
|
private:
|
||||||
asio::io_context io_context_;
|
asio::io_context io_context_;
|
||||||
asio::ip::tcp::socket socket_;
|
|
||||||
std::function<void(std::string)> callback_;
|
std::function<void(std::string)> callback_;
|
||||||
|
|
||||||
|
std::shared_ptr<Session> session_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NetworkClient(std::function<void(std::string)> callback);
|
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 connect(const std::string &host, uint16_t port);
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭到服务端的连接
|
|
||||||
*/
|
|
||||||
void disconnect();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向服务端发送消息
|
* 向服务端发送消息
|
||||||
* @param message 要发送的消息
|
* @param message 要发送的消息
|
||||||
*/
|
*/
|
||||||
void send(const std::string &message);
|
void send(const std::string &message) const;
|
||||||
|
|
||||||
[[nodiscard]] std::string read();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UNO::NETWORK
|
} // namespace UNO::NETWORK
|
||||||
|
|||||||
@@ -9,52 +9,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace UNO::NETWORK {
|
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()
|
void NetworkServer::accept()
|
||||||
{
|
{
|
||||||
this->acceptor_.async_accept([this](const asio::error_code &ec, asio::ip::tcp::socket socket) {
|
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)
|
void NetworkServer::addPlayer(asio::ip::tcp::socket socket)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(this->mutex_);
|
std::lock_guard<std::mutex> lock(this->mutex_);
|
||||||
this->sessions_[this->playerCount] = std::make_shared<Session>(playerCount, std::move(socket));
|
size_t playerId = this->playerCount;
|
||||||
this->sessions_[this->playerCount]->start(callback_);
|
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++;
|
this->playerCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
* @date 2025.11.25
|
* @date 2025.11.25
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Message.h"
|
|
||||||
|
|
||||||
|
#include "Session.h"
|
||||||
|
|
||||||
#include <asio.hpp>
|
#include <asio.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -14,32 +14,6 @@
|
|||||||
|
|
||||||
namespace UNO::NETWORK {
|
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 {
|
class NetworkServer {
|
||||||
private:
|
private:
|
||||||
asio::io_context io_context_;
|
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