개발자공부일기
패킷 길이문제 본문
버퍼객체를 주고받는 테스트를 하던 와중 이런 오류들이 클라이언트(unity)에서 발생했다. 뭐라는지 알아보자
Deserialize: Failed to deserialize data. Exception: System.IO.EndOfStreamException: Attempted to read past the end of the stream.
at ProtoBuf.ProtoReader+State.ThrowEoF () [0x00000] in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:809
at ProtoBuf.ProtoReader+StreamProtoReader.Ensure (ProtoBuf.ProtoReader+State& state, System.Int32 count, System.Boolean strict) [0x00106] in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:395
at ProtoBuf.ProtoReader+StreamProtoReader.ImplReadUInt32Fixed (ProtoBuf.ProtoReader+State& state) [0x00009] in /_/src/protobuf-net.Core/ProtoReader.Stream.cs:353
at (wrapper dynamic-method) LocationUpdate+UserLocation.proto_12(ProtoBuf.ProtoReader/State&,LocationUpdate/UserLocation)
at ProtoBuf.Internal.Serializers.SimpleCompiledSerializer`1[T].ProtoBuf.Serializers.ISerializer<T>.Read (ProtoBuf.ProtoReader+State& state, T value) [0x00000] in /_/src/protobuf-net/Internal/Serializers/CompiledSerializer.cs:107
at ProtoBuf.ProtoReader+State.ReadMessage[TSerializer,T] (ProtoBuf.Serializers.SerializerFeatures features, T value, TSerializer& serializer) [0x00007] in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:1022
at ProtoBuf.ProtoReader+State.FillBuffer[TSerializer,T] (ProtoBuf.Serializers.SerializerFeatures features, TSerializer& serializer, T initialValue) [0x0005f] in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:307
at ProtoBuf.Serializers.RepeatedSerializer`2[TCollection,TItem].ReadRepeated (ProtoBuf.ProtoReader+State& state, ProtoBuf.Serializers.SerializerFeatures features, TCollection values, ProtoBuf.Serializers.ISerializer`1[T] serializer) [0x00079] in /_/src/protobuf-net.Core/Serializers/RepeatedSerializer.cs:346
at (wrapper dynamic-method) LocationUpdate.proto_10(ProtoBuf.ProtoReader/State&,LocationUpdate)
at ProtoBuf.Internal.Serializers.SimpleCompiledSerializer`1[T].ProtoBuf.Serializers.ISerializer<T>.Read (ProtoBuf.ProtoReader+State& state, T value) [0x00000] in /_/src/protobuf-net/Internal/Serializers/CompiledSerializer.cs:107
at ProtoBuf.ProtoReader+State.ReadAsRoot[T] (T value, ProtoBuf.Serializers.ISerializer`1[T] serializer) [0x00031] in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:1157
at ProtoBuf.ProtoReader+State.DeserializeRoot[T] (T value, ProtoBuf.Serializers.ISerializer`1[T] serializer) [0x00000] in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:1137
at ProtoBuf.Serializer.Deserialize[T] (System.IO.Stream source) [0x0000f] in /_/src/protobuf-net/Serializer.Deserialize.cs:21
at Packets.Deserialize[T] (System.Byte[] data) [0x00007] in C:\Users\youmi\Desktop\node5_unity_sample-challenge2\Assets\Src\Codes\Packets.cs:29
UnityEngine.Debug:LogError (object)
Packets:Deserialize<LocationUpdate> (byte[]) (at Assets/Src/Codes/Packets.cs:34)
NetworkManager:HandleLocationPacket (byte[]) (at Assets/Src/Codes/NetworkManager.cs:289)
NetworkManager:ProcessReceivedData (byte[],int) (at Assets/Src/Codes/NetworkManager.cs:242)
NetworkManager/<ReceivePacketsAsync>d__24:MoveNext () (at Assets/Src/Codes/NetworkManager.cs:202)
UnityEngine.UnitySynchronizationContext:ExecuteTasks ()
맨위에 있는 오류다 굉장히 긴데 이 오류는 Protobuf를 이용해 데이터를 역직렬화(deserialization)할 때, 스트림 끝을 초과하여 데이터를 읽으려 할 때 발생하는 문제를 나타낸다.
서버가 보낸 버퍼가 잘못 되었거나 클라이언트가 제대로 버퍼를 읽지 못하거나 상호간 프로토형식이 일치하지 않는다거나 라고 생각하는데 GPT에 물어보니 다음과 같다.
주요 원인
- 전송된 데이터가 불완전함:
- 네트워크 전송 중 데이터가 손실되었거나 중단되어, ProtoBuf에서 역직렬화할 수 있는 완전한 데이터가 제공되지 않았을 가능성이 있습니다.
- 예를 들어, 패킷 크기를 잘못 계산하거나 데이터가 분리되어 처리되었을 수 있습니다.
- 역직렬화 대상 데이터 구조 불일치:
- 서버 또는 클라이언트에서 사용하는 데이터 구조 정의(.proto 파일)가 서로 다를 수 있습니다.
- 필드 추가, 삭제, 또는 타입 변경 시 이러한 오류가 발생할 수 있습니다.
- 패킷 크기 정보가 잘못 전달됨:
- 일반적으로 네트워크 프로토콜은 패킷 크기를 데이터 헤더에 포함합니다. 만약 크기 정보가 잘못되면, 스트림의 끝을 초과하여 읽으려 하게 됩니다.
- 올바르지 않은 데이터로 역직렬화 시도:
- 역직렬화 대상 데이터가 올바르지 않은 바이트 배열일 수 있습니다. 예를 들어, 다른 데이터 타입의 패킷을 잘못 전달했거나 데이터를 읽는 순서가 잘못된 경우입니다.
지금까지 진행했던걸 떠올려보면 1,4는 아니었다.
2번 아니면 3번 문제인데 그래서 일단 프로토파일을 다 체크해봤는데 일치했다.
그럼 3번이었고 유니티에서 보여준 에러중 2번째를 보면 HandleLocationPacket이 잘못된걸 볼 수 있다.
그래서 그 패킷을 보내는 곳을 찾아봤다. 그리고 패킷을 만들어 내는곳을 봤는데,
// 패킷 생성 함수
const makeNotification = (message, type) => {
// 패킷 길이 정보를 포함한 버퍼 생성
const packetLength = Buffer.alloc(4);
packetLength.writeUInt32BE(message.length + 1, 0); // 패킷 길이에 타입 바이트 포함
// 패킷 타입 정보를 포함한 버퍼 생성
const packetType = Buffer.alloc(1);
packetType.writeUInt8(type, 0);
// 길이 정보와 메시지를 함께 전송
return Buffer.concat([packetLength, packetType, message]);
};
이렇게 돼있었다. 지금 packetLength를 보면 메세지의 길이만을 더하고 있는데 우리가 보낼 패킷은 헤더도 들어간다.
내가 패킷길이에 헤더크기를 포함하지 않아서 클라이언트에서 요상한 패킷이라 본것이었다.
const makeNotification = (message, type) => {
// 패킷 길이 정보를 포함한 버퍼 생성
const packetLength = Buffer.alloc(4);
packetLength.writeUInt32BE(TOTAL_LENGTH + message.length + 1, 0); // 패킷 길이에 타입 바이트 포함
// 패킷 타입 정보를 포함한 버퍼 생성
const packetType = Buffer.alloc(1);
packetType.writeUInt8(type, 0);
// 길이 정보와 메시지를 함께 전송
return Buffer.concat([packetLength, packetType, message]);
};
그래서 packetLength에 헤더의 총 크기를 env에 정의해둔 TOTAL_LENGTH를 더해주었다.
그랬더니 해결!
'트러블슈팅' 카테고리의 다른 글
중복 랜더링 (0) | 2025.01.17 |
---|---|
웹소캣게임 트러블슈팅 (0) | 2024.12.18 |