인프런 커뮤니티 질문&답변

태사단님의 프로필 이미지
태사단

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

Serialization #3

두번째 출력부터 이름이 제대로 나오지 않습니다

작성

·

386

0

	class PlayerInfoReq : Packet
	{
		public long playerId;
		public string playerName;
		public string nickName;

		public PlayerInfoReq()
		{
			packetId = (ushort)PacketID.PlayerInfoReq;
		}

		public override ArraySegment<byte> Write()
		{
			ArraySegment<byte> segment = SendBufferHelper.Open(4096);

			ushort count = 0;
			bool success = true;

			Span<byte> span = new Span<byte>(segment.Array, segment.Offset, segment.Count);

			count += sizeof(ushort);
			success &= BitConverter.TryWriteBytes(span.Slice(count, span.Length - count), packetId);
			count += sizeof(ushort);
			success &= BitConverter.TryWriteBytes(span.Slice(count, span.Length - count), playerId);
			count += sizeof(long);


			ushort nameLen = (ushort)Encoding.Unicode.GetByteCount(playerName);
			success &= BitConverter.TryWriteBytes(span.Slice(count, span.Length - count), nameLen);
			count += sizeof(ushort);
			Array.Copy(Encoding.Unicode.GetBytes(playerName), 0, segment.Array, count, nameLen);
			count += nameLen;

			nameLen = (ushort)Encoding.Unicode.GetBytes(nickName, 0, nickName.Length, segment.Array, segment.Offset + count + sizeof(ushort));
			success &= BitConverter.TryWriteBytes(span.Slice(count, span.Length - count), nameLen);
			count += sizeof(ushort);
			count += nameLen;

			success &= BitConverter.TryWriteBytes(span, count);

			if (!success)
				return null;

			return SendBufferHelper.Close(count);
		}

		public override void Read(ArraySegment<byte> segment)
		{
			ushort count = 0;
			count += sizeof(ushort);
			count += sizeof(ushort);

			ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(segment.Array, segment.Offset, segment.Count);
			playerId = BitConverter.ToInt64(span.Slice(count, span.Length - count));
			count += sizeof(long);


			ushort nameLen = BitConverter.ToUInt16(span.Slice(count, span.Length - count));
			count += sizeof(ushort);
			playerName = Encoding.Unicode.GetString(span.Slice(count, nameLen));
			count += nameLen;

			nameLen = BitConverter.ToUInt16(span.Slice(count, span.Length - count));
			count += sizeof(ushort);
			nickName = Encoding.Unicode.GetString(span.Slice(count, nameLen));
			count += nameLen;
		}
	}

답변 5

2

Rookiss님의 프로필 이미지
Rookiss
지식공유자


이런 문제를 찾는 요령은
우선 클라 문제인지 서버 문제인지를 먼저 파악하는겁니다.
서버에서 받는 데이터 내용을 보니 1번째 데이터와 2번째 데이터가 상이한 것을 알 수 있고,
그렇다면 클라에서 전송하는 부분의 문제라는 것을 짐작할 수 있습니다.
데이터를 만들어주는 부분을 유심히 살펴보면
오프셋 계산이 잘못된 것을 확인할 수 있습니다.

0

태사단님의 프로필 이미지
태사단
질문자

앗... 첫 번째 string에 오프셋을 빠뜨렸네요. 그래서 playerName은 같은 곳에 계속 저장되니까 첫 번째 출력만 나왔고...

Read() 부분 문제인 줄 알고 한참 헤맸습니다 ㅠㅠ 감사합니다!

0

태사단님의 프로필 이미지
태사단
질문자

넵 방금 메일 보냈습니다!

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

안녕하세요,
프로젝트를 통으로 압축해서 rookiss@naver.com으로 보내주시면 살펴보겠습니다.
딱 그 버전에 맞는 코드가 없네요 :(

0

태사단님의 프로필 이미지
태사단
질문자

엇... 코드 빼고 본문 내용이 다 잘렸네요 ㅠ 간단하게 다시 적겠습니다

Serialization #3 강의에서 string을 직렬화하는 두 가지 방식이 나옵니다.

인코딩한 string을 Array.Copy로 복사하는 방법과, Encoding.Unicode.GetBytes에 오버로딩된 함수를 이용하여 인코딩 결과를 지정한 메모리 주소에 직접 입력하는 방식입니다.

두 방법을 다 실습해보고 싶어서 패킷 클래스에 playerName, nickName 두 가지 문자열 변수를 선언했습니다. 패킷을 보낼 때 값은 "이름", "닉네임" 으로 초기화했어요. 서버에서 Read()를 통해 읽은 후

Console.WriteLine($"Player Info Required : {packet.playerId} / {packet.nickName} ({packet.playerName})");

을 통해서 실행했더니,

위와 같이 두 번째 출력부터 playerName 문자열의 문자가 모두 NULL 문자(\0) 으로 나옵니다.

break point를 찍어보니 개수는 동일한데 \0\0\0... 이런 식으로 공백 문자로만 나오는데, 0으로 가득 찬 비트 배열을 읽고 있는 것 같습니다. 따로 예외 처리는 되지 않고요.

혹시 원인을 알려주실 수 있으신가요? 아무리 고민해봐도 모르겠어서 여쭤봅니다 ㅠㅠ 첫번째엔 왜 출력되는지도 모르겠습니다... 

태사단님의 프로필 이미지
태사단

작성한 질문수

질문하기