728x90
VV
- 서버에서 로그인 과정을 거쳤으니 그 결과를 다시 클라이언트에 보내줘야 한다. 나는 결과에 따라서 다른 프로토콜을 쓰는게 아니라 같은 프로토콜로 대신에 attribute에 다른 값으로 성공했는지 실패했는지 알아볼 수 있도록 구성했다.
bool OnDataHandle(IDataBuffer* pDataBuffer, int32_t nConnID)
{
if (pDataBuffer == nullptr)
{
CLog::GetInstancePtr()->LogError("Received null data buffer in OnDataHandle.");
return false;
}
PacketHeader* pHeader = (PacketHeader*)pDataBuffer->GetBuffer();
if (pHeader == nullptr)
{
CLog::GetInstancePtr()->LogError("Invalid packet header.");
return false;
}
int32_t MsgID = pHeader->MsgID;
switch (MsgID)
{
case EMessageID::LOGIN_REQUEST_MSG_ID:
{
string ReceiveData(pDataBuffer->GetData(), pDataBuffer->GetTotalLenth());
vector<string> ParsedData;
size_t pos = 0;
string token;
while ((pos = ReceiveData.find('|')) != string::npos)
{
token = ReceiveData.substr(0, pos);
ParsedData.push_back(token);
ReceiveData.erase(0, pos + 1);
}
ParsedData.push_back(ReceiveData);
if (ParsedData.size() == 2)
{
string ID = ParsedData[0];
string PW = ParsedData[1];
bool bIsValid = ValidateUserCredentials(ID, PW);
// TODO: Send success response to client
hbServerEngine::PacketHeader ResponseHeader;
ResponseHeader.MsgID = EMessageID::LOGIN_RESPONSE_MSG_ID;
ResponseHeader.TotalSize = sizeof(hbServerEngine::PacketHeader);
ResponseHeader.Attribute = bIsValid ? 0 : 1;
std::vector<uint8_t> ResponsePacket(sizeof(hbServerEngine::PacketHeader));
memcpy(ResponsePacket.data(), &ResponseHeader, sizeof(hbServerEngine::PacketHeader));
IDataBuffer* ResponseBuffer = CBufferAllocator::GetInstancePtr()->AllocDataBuff(ResponsePacket.size());
memcpy(ResponseBuffer->GetBuffer(), ResponsePacket.data(), ResponsePacket.size());
ResponseBuffer->SetTotalLenth(ResponsePacket.size());
CConnection* Connection = CConnectionMgr::GetInstancePtr()->GetConnectionByID(nConnID);
if (Connection)
{
Connection->SendBuffer(ResponseBuffer);
CNetManager::GetInstancePtr()->PostSendOperation(Connection);
}
}
break;
}
default:
CLog::GetInstancePtr()->LogWarn("Unhandled MsgID: %d", MsgID);
break;
}
- 서버쪽 코드를 좀 수정했다. 처음에는 if문으로 bIsValid에 따라 확인했는데, 다른 방법을 사용해서 구현했다.
void UNetworkManager::ProcessResponse(const TArray<uint8>& ReceiveData)
{
if (ReceiveData.Num() < sizeof(hbServerEngine::PacketHeader))
{
return;
}
hbServerEngine::PacketHeader* Header = (hbServerEngine::PacketHeader*)ReceiveData.GetData();
switch (Header->MsgID)
{
case EMessageID::LOGIN_RESPONSE_MSG_ID:
{
if (Header->Attribute == 0)
{
UE_LOG(LogTemp, Log, TEXT("Login successful!"));
//TODO 로그인 성공
}
else if (Header->Attribute == 1)
{
UE_LOG(LogTemp, Warning, TEXT("Login failed. Incorrect ID or Password."));
//TODO 로그인 실패 로직 처리
}
StopReceiving();
break;
}
default:
UE_LOG(LogTemp, Warning, TEXT("Unhandled MsgID: %d"), Header->MsgID);
break;
}
}
void UNetworkManager::ReceiveData()
{
if (ClientSocket)
{
ReceiveBuffer.SetNumUninitialized(8192);
int32 ReceivedDataSize = 0;
bool bReceive = ClientSocket->Recv(ReceiveBuffer.GetData(), ReceiveBuffer.Num(), ReceivedDataSize,
ESocketReceiveFlags::None);
if (bReceive && ReceivedDataSize > 0)
{
ReceiveBuffer.SetNum(ReceivedDataSize);
ProcessResponse(ReceiveBuffer);
}
else if (bReceive && ReceivedDataSize == 0)
{
// 서버에서 데이터를 아직 보내지 않았거나 수신할 데이터가 없는 경우.
UE_LOG(LogTemp, Log, TEXT("No data received, but connection is still active."));
}
else if (!bReceive)
{
// 데이터가 수신되지 않았거나 오류가 발생한 경우
if (ClientSocket->GetConnectionState() == SCS_Connected)
{
// 연결은 유지되고 있지만 데이터가 아직 도착하지 않은 경우
UE_LOG(LogTemp, Log, TEXT("No data received yet, connection is still valid."));
}
else
{
// 연결이 끊어진 경우
UE_LOG(LogTemp, Error, TEXT("Connection lost with server."));
}
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("ClientSocket is null, cannot receive data."));
}
}
void UNetworkManager::StartReceiving()
{
if (GetWorld())
{
GetWorld()->GetTimerManager().SetTimer(ReceiveTimerHandle, this, &UNetworkManager::ReceiveData, 0.1f, true);
}
}
void UNetworkManager::StopReceiving()
{
if (GetWorld())
{
GetWorld()->GetTimerManager().ClearTimer(ReceiveTimerHandle);
}
}
- NetworkManager.cpp에 새롭게 Receive코드를 구현해주었다.
결과
성공하는 것을 볼 수 있다.(야호)
다음은 클라이언트 움직임을 구현해보도록하겠다.
728x90
'Study > Project' 카테고리의 다른 글
VV 6. 장애물, UI 구현, 점수 구현 (0) | 2024.11.04 |
---|---|
VV 5. 움직임 구현 (Infinity Run), 점프, 슬라이드 (0) | 2024.10.30 |
VV 3. 로그인 기능 (0) | 2024.10.29 |
VV 트러블 슈팅 1. MSB3073 에러, NewObject with empty name can't be used to create default subobjects 에러 (0) | 2024.10.24 |
VV 2. 서버와의 연결 (0) | 2024.10.24 |