해결된 질문
작성
·
32
0
안녕하세요! 강의 내용은 name을 받는 과정에서 byte[] 직렬화 및 역직렬화 하기 위해 nameLen을 count하고, 이를 ArraySegment에 넣는 과정인데요. 그 과정에서 다음과 같은 코드를 사용합니다.
ServerSession.cs
이고, public override ArraySegment<byte> Write()
함수 내부입니다.
// string
ushort nameLen = (ushort)Encoding.Unicode.GetByteCount(name);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), nameLen);
count += sizeof(ushort); // nameLen(2)
Array.Copy(Encoding.Unicode.GetBytes(name), 0, segment.Array, count, nameLen);
count += nameLen; // name(n)
여기서 Array.Copy(Encoding.Unicode.GetBytes(name), 0, segment.Array, count, nameLen);
이 부분에서 count
대신 count + segment.Offset
를 사용하는 것이 올바르지 않을까 하여 질문드립니다.
이는 for문을 포함하여 코드 실행시 서버 측에서 다음과 같이 나타나기 때문입니다.
Listening...
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=
Received packet: size=20, packetId=1
Client connected: [fe80::9e56:3a99:3a3a:58be%18]:55626
OnDisconnected: [fe80::9e56:3a99:3a3a:58be%18]:55626
이처럼, 첫 1회만 NPC라는 네임이 제대로 나타나는 것을 볼 수 있습니다.
그러나 count + segment.Offset
를 사용했을 경우는, 다음과 같이 제대로 나타납니다.
Listening...
Client connected: [fe80::9e56:3a99:3a3a:58be%18]:55458
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
PlayerInfoReq: playerId=1001, Name=NPC
Received packet: size=20, packetId=1
OnDisconnected: [fe80::9e56:3a99:3a3a:58be%18]:55458
물론 이후 리팩토링을 통해 작성한 코드에서는 전부 제대로 나타납니다.
ushort nameLen = (ushort)Encoding.Unicode.GetBytes(this.name, 0, this.name.Length, segment.Array, segment.Offset + count + sizeof(ushort));
(리팩토링 코드)
Offset을 사용하지 않을 경우 아마도 패킷을 덮어써서 이런 결과가 나타나는 것 같습니다.
답변 2
1
0
안녕하세요, Rein님. 인프런 AI 인턴입니다.
질문해주신 내용은 패킷 직렬화 중에서 문자열을 제대로 직렬화하지 못해 발생하는 문제점과 그 해결책을 탐구하는 과정 같습니다. 특히, ArraySegment
를 이용한 데이터 저장 시 Offset
의 사용이 핵심입니다.
문제 발생: Array.Copy()
를 사용할 때 count
인덱스 대신 count + segment.Offset
를 사용하지 않는 경우, 초기 패킷 이외의 데이터가 저장될 때 덮어씌워지는 문제가 발생합니다. 이것은 데이터가 저장되어야 할 적절한 위치를 지정하지 않았기 때문입니다.
해결 법: 조정된 코드에서는 count + segment.Offset
를 사용하여 데이터가 저장될 위치를 명확히 지정해 줌으로써 모든 패킷에서 문자열이 제대로 직렬화 및 역직렬화 됩니다. 이는 ArraySegment
가 메모리의 특정 부분을 나타내기 때문에 Offset
을 사용해 주어진 배열의 적절한 시작 지점을 지정해야 함을 보여줍니다.
리팩토링 개선: 또한, 질문에 언급된 리팩토링 코드에서는 Encoding.Unicode.GetBytes
에 segment.Offset
을 포함하여 직접 사용하는 것으로, 초기 2 바이트
를 보낸 후 이름 데이터를 바로 처리하는 형태로 개선되었습니다.
관련하여 유사한 주제를 다룬 질문을 참고하시면 도움이 될 수 있습니다:
9분 50초부분부터 궁금한게 있습니다: 패킷의 크기를 적절히 관리하고 잘못된 값을 피하기 위해 sizeof(ushort)
등을 사용하는 사례에 대해 설명합니다.
두번째 출력부터 이름이 제대로 나오지 않습니다: 데이터의 오프셋이 잘못되어 문자열이 제대로 나오지 않는 문제와 그 해결 방법에 대한 설명이 있습니다.
이 링크들은 문자열 직렬화 및 역직렬화 과정에서 Offset
를 포함한 데이터 위치 문제에 대한 이해를 도와줄 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.