feat: 중복 로그인 방지 코드 추가
This commit is contained in:
parent
1d103d7f16
commit
17013f70f5
6 changed files with 102 additions and 7 deletions
|
|
@ -33,13 +33,38 @@ bool BaseClient::ReceiveHeader(PacketHeader &header) {
|
|||
}
|
||||
}
|
||||
|
||||
void BaseClient::Login(const std::string &nickname) {
|
||||
bool BaseClient::Login(const std::string &nickname) {
|
||||
PKT_CS_Login loginPkt;
|
||||
std::memset(loginPkt.nickname, 0, sizeof(loginPkt.nickname));
|
||||
std::strncpy(loginPkt.nickname, nickname.c_str(),
|
||||
sizeof(loginPkt.nickname) - 1);
|
||||
SendPacket(PacketID::Login, &loginPkt, sizeof(loginPkt));
|
||||
std::cout << "로그인 요청 보냄: " << nickname << std::endl;
|
||||
|
||||
// 로그인 결과 대기
|
||||
PacketHeader header;
|
||||
if (!ReceiveHeader(header) ||
|
||||
header.id != static_cast<uint16_t>(PacketID::SC_LoginResult)) {
|
||||
std::cerr << "로그인 응답을 받지 못했습니다." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
PKT_SC_LoginResult res;
|
||||
if (!ReceivePayload(res)) {
|
||||
std::cerr << "로그인 응답 수신 실패" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (res.result == 1) {
|
||||
std::cout << "로그인 성공!" << std::endl;
|
||||
return true;
|
||||
} else if (res.result == 0) {
|
||||
std::cerr << "로그인 실패: 이미 접속 중인 유저입니다." << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
std::cerr << "로그인 실패: 알 수 없는 오류" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseClient::HandleUpgradeResult() {
|
||||
|
|
@ -68,7 +93,10 @@ void BaseClient::HandleSellResult() {
|
|||
void InteractiveClient::Run() {
|
||||
std::cout << "닉네임을 입력하세요: ";
|
||||
std::cin >> nickname_;
|
||||
Login(nickname_);
|
||||
if (!Login(nickname_)) {
|
||||
std::cerr << "로그인에 실패하여 종료합니다." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (currentLevel_ == 0) {
|
||||
|
|
@ -128,7 +156,10 @@ void ScenarioClient::Run() {
|
|||
|
||||
if (!(is >> nickname_))
|
||||
return;
|
||||
Login(nickname_);
|
||||
if (!Login(nickname_)) {
|
||||
std::cerr << "로그인에 실패하여 종료합니다." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (is >> line) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void Login(const std::string &nickname);
|
||||
bool Login(const std::string &nickname);
|
||||
|
||||
virtual void Run() = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ enum class PacketID : uint16_t {
|
|||
Ping = 1,
|
||||
// 로그인 요청 (PKT_CS_Login)
|
||||
Login = 10,
|
||||
// 로그인 결과 응답 (PKT_SC_LoginResult)
|
||||
SC_LoginResult = 11,
|
||||
Chat = 20,
|
||||
|
||||
// 검 키우기 관련 패킷
|
||||
|
|
@ -52,6 +54,11 @@ struct PKT_CS_Login {
|
|||
char nickname[32];
|
||||
};
|
||||
|
||||
struct PKT_SC_LoginResult {
|
||||
// 0: 이미 접속 중, 1: 성공
|
||||
uint8_t result;
|
||||
};
|
||||
|
||||
struct PKT_SC_UpgradeResult {
|
||||
// 0: 파괴, 1: 성공, 2: 실패
|
||||
uint8_t result;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,50 @@ PacketHandler::HandlePacket(std::shared_ptr<Session> session,
|
|||
|
||||
auto userData = co_await DatabaseManager::GetInstance().LoadUser(nickname);
|
||||
|
||||
session->SetNickname(userData.nickname);
|
||||
// 골드와 검 레벨 설정 (닉네임은 TryJoin에서 설정)
|
||||
session->SetGold(userData.gold);
|
||||
session->SetSwordLevel(userData.swordLevel);
|
||||
|
||||
Logger::Log("클라이언트 로그인: ", nickname, " (Gold: ", session->GetGold(),
|
||||
PKT_SC_LoginResult loginResult;
|
||||
|
||||
// 원자적으로 중복 체크 및 세션 추가
|
||||
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);
|
||||
co_return;
|
||||
}
|
||||
|
||||
Logger::Log("클라이언트 로그인 성공: ", nickname,
|
||||
" (Gold: ", session->GetGold(),
|
||||
", Level: ", session->GetSwordLevel(), ")");
|
||||
|
||||
SessionManager::GetInstance().Join(session);
|
||||
// 로그인 성공 응답
|
||||
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);
|
||||
} break;
|
||||
|
||||
case PacketID::CS_UpgradeSword: {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,26 @@ void SessionManager::Leave(std::shared_ptr<Session> session) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SessionManager::TryJoin(std::shared_ptr<Session> session,
|
||||
const std::string &nickname) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// 중복 체크
|
||||
for (const auto &existing : sessions_) {
|
||||
if (existing->GetNickname() == nickname) {
|
||||
Logger::Log("이미 접속 중인 유저 로그인 시도: ", nickname);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 중복이 없으면 닉네임 설정 후 추가
|
||||
session->SetNickname(nickname);
|
||||
sessions_.insert(session);
|
||||
Logger::Log("클라이언트[", nickname,
|
||||
"]가 입장했습니다. 총 세션 수: ", sessions_.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionManager::Broadcast(PacketHeader header,
|
||||
std::span<const uint8_t> body) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue