36. Serialization #3 에서 string (name) 코드 수정 질문
안녕하세요! 강의 내용은 name을 받는 과정에서 byte[] 직렬화 및 역직렬화 하기 위해 nameLen을 count하고, 이를 ArraySegment에 넣는 과정인데요. 그 과정에서 다음과 같은 코드를 사용합니다.
ServerSession.cs 이고, public override ArraySegment<byte> Write()함수 내부입니다.
// stringushort 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을 사용하지 않을 경우 아마도 패킷을 덮어써서 이런 결과가 나타나는 것 같습니다.
Answer 2
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를 포함한 데이터 위치 문제에 대한 이해를 도와줄 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
TLS 질문드립니다.
0
34
2
SpinLock과 컨텍스트스위칭에 대해 질문 남겨요.
0
39
2
Unity Span
0
65
2
XML, Dll 차이점
0
99
2
Session 질문입니다
0
74
1
Write Read 커서 키워드
0
69
1
더미 클라이언트 수에 따른 OnDisconnect 발생
0
65
2
네트워크 Send 전담 스레드 배치
0
94
2
UnhandledException 으로 서버 터지는 경우
0
82
2
컨텐츠 단, 엔진 단
0
100
1
질문 있습니다
0
73
2
C# 게임서버 3D MMORPG
0
141
2
유니티6 버전
0
94
2
receive하는 부분과 send하는 부분의 차이
0
128
2
커서의 위치의 중요성
0
99
2
C++ 전혀 모르는데 C# 서버
0
164
2
강의에 질문이 있습니다
0
83
2
멀티스레드 이해도 질문
0
90
1
500 vs 500
0
122
3
OnAcceptHandler 액션 함수
0
57
1
이 정도 서버의 객관적인 수준이 궁금합니다.
0
185
2
외부 컴퓨터와의 통신 방법이 궁금합니다
0
100
1
스핀락 질문.
0
104
2
안녕하세요 취업 학원 관련해서 문의드립니다.
0
174
2

