Compare commits

...

3 commits

9 changed files with 40 additions and 61 deletions

View file

@ -51,3 +51,6 @@ cmake --build build
- SessionManager: 글로벌 세션 관리 및 브로드캐스팅
- DatabaseManager: 비동기 데이터베이스 작업 및 락 제어
- Packet: 바이너리 프로토콜 정의 (pragma pack(1))
## TODO: 완성도 위한 개선
- 진행중인 검 상태 저장 후 재접속 시 복구

View file

@ -8,7 +8,8 @@ using boost::asio::ip::tcp;
class NetworkService {
public:
NetworkService(uint16_t port, int threadCount);
NetworkService(boost::asio::io_context &io_context, uint16_t port,
int threadCount);
~NetworkService();
void Run();
@ -17,7 +18,7 @@ public:
private:
void DoAccept();
boost::asio::io_context io_context_;
boost::asio::io_context &io_context_;
std::vector<std::jthread> threads_;
tcp::acceptor acceptor_;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>

View file

@ -16,6 +16,20 @@ public:
void Start();
void Send(std::span<const uint8_t> data);
template <typename T> void SendPacket(PacketID id, const T &payload) {
PacketHeader header;
header.id = static_cast<uint16_t>(id);
header.size = sizeof(T);
std::vector<uint8_t> buffer(sizeof(PacketHeader) + sizeof(T));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
std::memcpy(buffer.data() + sizeof(PacketHeader), &payload, sizeof(T));
Send(buffer);
}
void SendPacket(PacketID id);
void SetNickname(const std::string &nickname);
const std::string &GetNickname() const;

View file

@ -10,7 +10,6 @@ class SessionManager {
public:
static SessionManager &GetInstance();
void Join(std::shared_ptr<Session> session);
bool TryJoin(std::shared_ptr<Session> session, const std::string &nickname);
void Leave(std::shared_ptr<Session> session);
void Broadcast(PacketHeader header, std::span<const uint8_t> body);

View file

@ -2,8 +2,10 @@
#include "Logger.h"
#include "Session.h"
NetworkService::NetworkService(uint16_t port, int threadCount)
: acceptor_(io_context_, tcp::endpoint(tcp::v4(), port)),
NetworkService::NetworkService(boost::asio::io_context &io_context,
uint16_t port, int threadCount)
: io_context_(io_context),
acceptor_(io_context_, tcp::endpoint(tcp::v4(), port)),
work_guard_(boost::asio::make_work_guard(io_context_)) {
threads_.reserve(threadCount);
for (int i = 0; i < threadCount; ++i) {

View file

@ -13,9 +13,7 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
switch (static_cast<PacketID>(packet.header.id)) {
case PacketID::Ping: {
Logger::Log("Ping 수신됨");
session->Send(std::span<const uint8_t>(
reinterpret_cast<const uint8_t *>(&packet.header),
sizeof(PacketHeader)));
session->SendPacket(PacketID::Ping);
} break;
case PacketID::CS_Login: {
@ -40,18 +38,7 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
if (!SessionManager::GetInstance().TryJoin(session, userData.nickname)) {
Logger::Log("중복 로그인 거부: ", nickname);
loginResult.result = 0;
PacketHeader header;
header.id = static_cast<uint16_t>(PacketID::SC_LoginResult);
header.size = sizeof(PKT_SC_LoginResult);
std::vector<uint8_t> buffer(sizeof(PacketHeader) +
sizeof(PKT_SC_LoginResult));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
std::memcpy(buffer.data() + sizeof(PacketHeader), &loginResult,
sizeof(PKT_SC_LoginResult));
session->Send(buffer);
session->SendPacket(PacketID::SC_LoginResult, loginResult);
co_return;
}
@ -60,18 +47,7 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
", Level: ", session->GetSwordLevel(), ")");
loginResult.result = 1;
PacketHeader header;
header.id = static_cast<uint16_t>(PacketID::SC_LoginResult);
header.size = sizeof(PKT_SC_LoginResult);
std::vector<uint8_t> buffer(sizeof(PacketHeader) +
sizeof(PKT_SC_LoginResult));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
std::memcpy(buffer.data() + sizeof(PacketHeader), &loginResult,
sizeof(PKT_SC_LoginResult));
session->Send(buffer);
session->SendPacket(PacketID::SC_LoginResult, loginResult);
} break;
case PacketID::CS_UpgradeSword: {
@ -104,16 +80,7 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
res.currentGold = session->GetGold();
// 결과 패킷 전송
PacketHeader header;
header.id = static_cast<uint16_t>(PacketID::SC_UpgradeResult);
header.size = sizeof(PKT_SC_UpgradeResult);
std::vector<uint8_t> buffer(sizeof(PacketHeader) +
sizeof(PKT_SC_UpgradeResult));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
std::memcpy(buffer.data() + sizeof(PacketHeader), &res,
sizeof(PKT_SC_UpgradeResult));
session->Send(buffer);
session->SendPacket(PacketID::SC_UpgradeResult, res);
// 브로드캐스트
if (currentGold >= cost) {
@ -158,17 +125,7 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
res.earnedGold = price;
res.totalGold = newGold;
PacketHeader header;
header.id = static_cast<uint16_t>(PacketID::SC_SellResult);
header.size = sizeof(PKT_SC_SellResult);
std::vector<uint8_t> buffer(sizeof(PacketHeader) +
sizeof(PKT_SC_SellResult));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
std::memcpy(buffer.data() + sizeof(PacketHeader), &res,
sizeof(PKT_SC_SellResult));
session->Send(buffer);
session->SendPacket(PacketID::SC_SellResult, res);
Logger::Log("검 판매 [", session->GetNickname(), "]: ", price,
" 골드 획득");

View file

@ -3,6 +3,7 @@
#include "SessionManager.h"
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <cstring>
Session::Session(tcp::socket socket) : socket_(std::move(socket)) {}
@ -21,6 +22,15 @@ uint32_t Session::GetSwordLevel() const { return swordLevel_; }
void Session::Start() { DoReadHeader(); }
void Session::SendPacket(PacketID id) {
PacketHeader header;
header.id = static_cast<uint16_t>(id);
header.size = 0;
std::vector<uint8_t> buffer(sizeof(PacketHeader));
std::memcpy(buffer.data(), &header, sizeof(PacketHeader));
Send(buffer);
}
void Session::Send(std::span<const uint8_t> data) {
auto self(shared_from_this());
boost::asio::post(

View file

@ -6,13 +6,6 @@ SessionManager &SessionManager::GetInstance() {
return instance;
}
void SessionManager::Join(std::shared_ptr<Session> session) {
std::lock_guard<std::mutex> lock(mutex_);
sessions_.insert(session);
Logger::Log("클라이언트[", session->GetNickname(),
"]가 입장했습니다. 총 세션 수: ", sessions_.size());
}
void SessionManager::Leave(std::shared_ptr<Session> session) {
std::lock_guard<std::mutex> lock(mutex_);
if (sessions_.erase(session) > 0) {

View file

@ -32,7 +32,7 @@ int main() {
return 1;
}
NetworkService server(port, threadCount);
NetworkService server(main_context, port, threadCount);
server.Run();
boost::asio::signal_set signals(main_context, SIGINT, SIGTERM);