Compare commits
No commits in common. "c306c4233a52f8392f3a31e1029d7ac847fce7d8" and "9f5fe4ede7ce44c7263b21558e6c6e5b8ce0d750" have entirely different histories.
c306c4233a
...
9f5fe4ede7
9 changed files with 61 additions and 40 deletions
|
|
@ -51,6 +51,3 @@ cmake --build build
|
||||||
- SessionManager: 글로벌 세션 관리 및 브로드캐스팅
|
- SessionManager: 글로벌 세션 관리 및 브로드캐스팅
|
||||||
- DatabaseManager: 비동기 데이터베이스 작업 및 락 제어
|
- DatabaseManager: 비동기 데이터베이스 작업 및 락 제어
|
||||||
- Packet: 바이너리 프로토콜 정의 (pragma pack(1))
|
- Packet: 바이너리 프로토콜 정의 (pragma pack(1))
|
||||||
|
|
||||||
## TODO: 완성도 위한 개선
|
|
||||||
- 진행중인 검 상태 저장 후 재접속 시 복구
|
|
||||||
|
|
@ -8,8 +8,7 @@ using boost::asio::ip::tcp;
|
||||||
|
|
||||||
class NetworkService {
|
class NetworkService {
|
||||||
public:
|
public:
|
||||||
NetworkService(boost::asio::io_context &io_context, uint16_t port,
|
NetworkService(uint16_t port, int threadCount);
|
||||||
int threadCount);
|
|
||||||
~NetworkService();
|
~NetworkService();
|
||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|
@ -18,7 +17,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void DoAccept();
|
void DoAccept();
|
||||||
|
|
||||||
boost::asio::io_context &io_context_;
|
boost::asio::io_context io_context_;
|
||||||
std::vector<std::jthread> threads_;
|
std::vector<std::jthread> threads_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
|
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,6 @@ public:
|
||||||
void Start();
|
void Start();
|
||||||
void Send(std::span<const uint8_t> data);
|
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);
|
void SetNickname(const std::string &nickname);
|
||||||
const std::string &GetNickname() const;
|
const std::string &GetNickname() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class SessionManager {
|
||||||
public:
|
public:
|
||||||
static SessionManager &GetInstance();
|
static SessionManager &GetInstance();
|
||||||
|
|
||||||
|
void Join(std::shared_ptr<Session> session);
|
||||||
bool TryJoin(std::shared_ptr<Session> session, const std::string &nickname);
|
bool TryJoin(std::shared_ptr<Session> session, const std::string &nickname);
|
||||||
void Leave(std::shared_ptr<Session> session);
|
void Leave(std::shared_ptr<Session> session);
|
||||||
void Broadcast(PacketHeader header, std::span<const uint8_t> body);
|
void Broadcast(PacketHeader header, std::span<const uint8_t> body);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,8 @@
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
|
|
||||||
NetworkService::NetworkService(boost::asio::io_context &io_context,
|
NetworkService::NetworkService(uint16_t port, int threadCount)
|
||||||
uint16_t port, int threadCount)
|
: acceptor_(io_context_, tcp::endpoint(tcp::v4(), port)),
|
||||||
: io_context_(io_context),
|
|
||||||
acceptor_(io_context_, tcp::endpoint(tcp::v4(), port)),
|
|
||||||
work_guard_(boost::asio::make_work_guard(io_context_)) {
|
work_guard_(boost::asio::make_work_guard(io_context_)) {
|
||||||
threads_.reserve(threadCount);
|
threads_.reserve(threadCount);
|
||||||
for (int i = 0; i < threadCount; ++i) {
|
for (int i = 0; i < threadCount; ++i) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
||||||
switch (static_cast<PacketID>(packet.header.id)) {
|
switch (static_cast<PacketID>(packet.header.id)) {
|
||||||
case PacketID::Ping: {
|
case PacketID::Ping: {
|
||||||
Logger::Log("Ping 수신됨");
|
Logger::Log("Ping 수신됨");
|
||||||
session->SendPacket(PacketID::Ping);
|
session->Send(std::span<const uint8_t>(
|
||||||
|
reinterpret_cast<const uint8_t *>(&packet.header),
|
||||||
|
sizeof(PacketHeader)));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PacketID::CS_Login: {
|
case PacketID::CS_Login: {
|
||||||
|
|
@ -38,7 +40,18 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
||||||
if (!SessionManager::GetInstance().TryJoin(session, userData.nickname)) {
|
if (!SessionManager::GetInstance().TryJoin(session, userData.nickname)) {
|
||||||
Logger::Log("중복 로그인 거부: ", nickname);
|
Logger::Log("중복 로그인 거부: ", nickname);
|
||||||
loginResult.result = 0;
|
loginResult.result = 0;
|
||||||
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
||||||
|
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);
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +60,18 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
||||||
", Level: ", session->GetSwordLevel(), ")");
|
", Level: ", session->GetSwordLevel(), ")");
|
||||||
|
|
||||||
loginResult.result = 1;
|
loginResult.result = 1;
|
||||||
session->SendPacket(PacketID::SC_LoginResult, loginResult);
|
|
||||||
|
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);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PacketID::CS_UpgradeSword: {
|
case PacketID::CS_UpgradeSword: {
|
||||||
|
|
@ -80,7 +104,16 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
||||||
res.currentGold = session->GetGold();
|
res.currentGold = session->GetGold();
|
||||||
|
|
||||||
// 결과 패킷 전송
|
// 결과 패킷 전송
|
||||||
session->SendPacket(PacketID::SC_UpgradeResult, res);
|
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);
|
||||||
|
|
||||||
// 브로드캐스트
|
// 브로드캐스트
|
||||||
if (currentGold >= cost) {
|
if (currentGold >= cost) {
|
||||||
|
|
@ -125,7 +158,17 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
||||||
res.earnedGold = price;
|
res.earnedGold = price;
|
||||||
res.totalGold = newGold;
|
res.totalGold = newGold;
|
||||||
|
|
||||||
session->SendPacket(PacketID::SC_SellResult, res);
|
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);
|
||||||
|
|
||||||
Logger::Log("검 판매 [", session->GetNickname(), "]: ", price,
|
Logger::Log("검 판매 [", session->GetNickname(), "]: ", price,
|
||||||
" 골드 획득");
|
" 골드 획득");
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include "SessionManager.h"
|
#include "SessionManager.h"
|
||||||
#include <boost/asio/co_spawn.hpp>
|
#include <boost/asio/co_spawn.hpp>
|
||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
Session::Session(tcp::socket socket) : socket_(std::move(socket)) {}
|
Session::Session(tcp::socket socket) : socket_(std::move(socket)) {}
|
||||||
|
|
||||||
|
|
@ -22,15 +21,6 @@ uint32_t Session::GetSwordLevel() const { return swordLevel_; }
|
||||||
|
|
||||||
void Session::Start() { DoReadHeader(); }
|
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) {
|
void Session::Send(std::span<const uint8_t> data) {
|
||||||
auto self(shared_from_this());
|
auto self(shared_from_this());
|
||||||
boost::asio::post(
|
boost::asio::post(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,13 @@ SessionManager &SessionManager::GetInstance() {
|
||||||
return instance;
|
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) {
|
void SessionManager::Leave(std::shared_ptr<Session> session) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (sessions_.erase(session) > 0) {
|
if (sessions_.erase(session) > 0) {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ int main() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkService server(main_context, port, threadCount);
|
NetworkService server(port, threadCount);
|
||||||
server.Run();
|
server.Run();
|
||||||
|
|
||||||
boost::asio::signal_set signals(main_context, SIGINT, SIGTERM);
|
boost::asio::signal_set signals(main_context, SIGINT, SIGTERM);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue