Skip to content

Commit

Permalink
[feat] Gather 알고리즘 개선 및 버그 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
hagukin committed Oct 17, 2023
1 parent 95b2627 commit 5bb335b
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Source/IocpGame/NetCodes/NetBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void SendBuffer::SetDefaultHeader()
// 여기서 정의된 헤더값들은 유효하지 않기 때문에 반드시 발송 전에 적절한 헤더 값으로 교체해 주는 작업이 필요
// 단 size의 경우에는 Write() 과정에서 알아서 업데이트 되기 때문에 senderType과 id만 제대로 입력해주면 됨
((PacketHeader*)Buffer)->uniqueId = 0;
((PacketHeader*)Buffer)->packetOrder = 0;
((PacketHeader*)Buffer)->packetOrder = 1;
((PacketHeader*)Buffer)->fragmentCount = 1;
((PacketHeader*)Buffer)->size = sizeof(PacketHeader);
((PacketHeader*)Buffer)->senderType = HostTypeEnum::NONE;
Expand Down
7 changes: 5 additions & 2 deletions Source/IocpGame/PacketCodes/GameStateApplier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,24 @@ bool GameStateApplier::ApplyPacket_UEClient(TSharedPtr<RecvBuffer> packet, ANetH
// 패킷 순서 검증 (TCP지만 만일의 사태를 대비)
if (!netHandler->GetDeserializerShared()->IsCorrectPacket(packet->GetHeader()))
{
netHandler->GetDeserializerShared()->ResetPacketInfo();
netHandler->GetDeserializerShared()->Clear(); // 그동안 수신한 버퍼 Fragment 삭제
return true;
}

// 버퍼 복사
netHandler->GetDeserializerShared()->SetPacketInfo(packet->GetHeader());
netHandler->GetDeserializerShared()->ReadDataFromBuffer(packet);

// 마지막 패킷 fragment일 경우
if (netHandler->GetDeserializerShared()->SetPacketInfo(packet->GetHeader()))
// 마지막 fragment일 경우
if (packet->GetHeader()->packetOrder == packet->GetHeader()->fragmentCount)
{
SD_GameState* gameState = new SD_GameState();
netHandler->GetDeserializerShared()->Deserialize((SD_Data*)gameState);
Cast<URovenhellGameInstance>(GameInstance)->TickCounter->SetServerTick_UEClient(gameState->Tick); // 서버 틱과 동기화
ApplyPhysicsAndSyncPlayers_UEClient(gameState, netHandler); // 데이터 처리
// TODO: GameState 내의 다른 데이터들도 처리
netHandler->GetDeserializerShared()->ResetPacketInfo();
netHandler->GetDeserializerShared()->Clear(); // 처리를 완료한 버퍼 Fragment 삭제
}
return true;
Expand Down
4 changes: 2 additions & 2 deletions Source/IocpGame/PacketCodes/PacketHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

struct PacketHeader
{
uint8 uniqueId; // 고유 식별자
uint8 packetOrder; // 이 패킷 조각이 전체 데이터에서 몇번째인지
uint8 uniqueId; // 고유 식별자 (1 이상)
uint8 packetOrder; // 이 패킷 조각이 전체 데이터에서 몇번째인지 (1부터 시작)
uint8 fragmentCount; // 전체 데이터가 몇 개의 조각들로 구성되어 있는지
uint16 size; // 헤더를 포함한 이 단일 패킷(fragment)의 총 크기
uint16 senderType; // 발신자 타입 (ExecType)
Expand Down
19 changes: 5 additions & 14 deletions Source/IocpGame/PacketCodes/SerializeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,14 @@ bool SerializeManager::ReadDataFromBuffer(TSharedPtr<RecvBuffer> readBuffer)
void SerializeManager::ResetPacketInfo()
{
ReceivedPacketId = 0;
ReceivedFragments.Reset();
LasReceivedFragmentsNumber = 0;
}

bool SerializeManager::IsCorrectPacket(const PacketHeader* packetHeader)
{
if (ReceivedPacketId != 0 && ReceivedPacketId != packetHeader->uniqueId)
if (LasReceivedFragmentsNumber + 1 != packetHeader->packetOrder)
{
UE_LOG(LogTemp, Error, TEXT("패킷 로스가 발생했거나, 혹은 알 수 없는 이유로 패킷 순서가 뒤바뀌었습니다! 기존 수신하던 패킷 fragment들은 삭제됩니다."));
ResetPacketInfo();
UE_LOG(LogTemp, Error, TEXT("패킷 로스가 발생했거나, 혹은 알 수 없는 이유로 패킷 순서가 뒤바뀌었습니다!"));
return false;
}
return true;
Expand All @@ -84,14 +83,6 @@ bool SerializeManager::IsCorrectPacket(const PacketHeader* packetHeader)
bool SerializeManager::SetPacketInfo(const PacketHeader* packetHeader)
{
ReceivedPacketId = packetHeader->uniqueId;
ReceivedFragments.Add(packetHeader->packetOrder, true);

// TCP 패킷이므로 순서 보장
if (packetHeader->packetOrder == packetHeader->fragmentCount - 1) // 인덱스 == size - 1
{
// 마지막 패킷 수신 완료
ResetPacketInfo();
return true;
}
return false;
LasReceivedFragmentsNumber = packetHeader->packetOrder;
return true;
}
4 changes: 2 additions & 2 deletions Source/IocpGame/PacketCodes/SerializeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ class IOCPGAME_API SerializeManager
TUniquePtr<TArray<uint8>> Array;

private:
uint8 ReceivedPacketId; // 현재 수신 중인 패킷의 UniqueId
TMap<uint8, bool> ReceivedFragments; // 수신한 패킷 조각들
uint8 ReceivedPacketId = 0; // 현재 수신 중인 패킷의 UniqueId
uint8 LasReceivedFragmentsNumber = 0; // 수신한 패킷 조각들; 0이면 한 조각도 수신받지 못한 상태를 의미
};
4 changes: 2 additions & 2 deletions Source/IocpGame/Private/NetHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void ANetHandler::RegisterSend_UEClient(float DeltaTime)
// 2) Scatter-Gather 사용시 서버에 막대한 부담이 가해지기 때문이다
FillPacketSenderTypeHeader(writeBuf);
writeBuf->GetHeader()->uniqueId = GenerateUniquePacketId();
writeBuf->GetHeader()->packetOrder = 0;
writeBuf->GetHeader()->packetOrder = 1;
writeBuf->GetHeader()->fragmentCount = 1;
writeBuf->GetHeader()->senderId = GetSessionShared()->GetSessionId();
writeBuf->GetHeader()->protocol = PacketProtocol::CLIENT_ALLOW_MULTIPLE_PER_TICK;
Expand Down Expand Up @@ -419,7 +419,7 @@ void ANetHandler::RegisterSend_UEServer(float DeltaTime)
uint8 totalFragmentCount = (uint8)FMath::CeilToInt((float)Serializer->Array->Num() / (NetBufferManager::SendBufferSize - sizeof(PacketHeader)));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("전송 패킷 갯수: %i"), totalFragmentCount)); // TESTING

int packetCount = 0;
int packetCount = 1;
for (int i = 0; i < Serializer->Array->Num(); i += NetBufferManager::SendBufferSize - sizeof(PacketHeader))
{
TSharedPtr<SendBuffer> writeBuf = nullptr;
Expand Down

0 comments on commit 5bb335b

Please sign in to comment.