송신 측은 패킷을 만들어 보내기 위해 데이터들을 바이트 단위로 만들어 내고,
수신 측은 받은 바이트 데이터들을 예상하는 데이터들로 변환하는 과정
public override void Read(ArraySegment<byte> segment)
{
ushort count = 0;
ReadOnlySpan<byte> s = new ReadOnlySpan<byte>(segment.Array, segment.Offset, segment.Count);
count += sizeof(ushort); // packet size count
count += sizeof(ushort); // packet id count
this.playerID = BitConverter.ToInt64(s.Slice(count, s.Length - count));
count += sizeof(long); //long data count
ushort nameLength = BitConverter.ToUInt16(s.Slice(count, s.Length - count));
count += sizeof(ushort); //ushort data count
this.name = Encoding.Unicode.GetString(s.Slice(count, nameLength));
count += nameLength; //string data count
ushort skillCount = BitConverter.ToUInt16(s.Slice(count, s.Length - count));
count += sizeof(ushort);
skills.Clear();
for (int i = 0; i < skillCount; i++)
{
SkillInfo newSkill = new SkillInfo();
newSkill.Read(s, ref count); //struct data count
skills.Add(newSkill);
}
}
패킷을 받은 후 저장된 버퍼를 가지고 데이터 순서 및 크기대로 파싱
string과 같은 가변적 데이터는 데이터의 byte 길이를 먼저 받아 해당 길이만큼을 파싱
list같은 컨테이너는 데이터의 수를 먼저 받고, 해당 데이터만큼을 반복하며 파싱
public override ArraySegment<byte> Write()
{
ArraySegment<byte> segment = SendBufferHelper.Open(4096);
Span<byte> s = new Span<byte>(segment.Array, segment.Offset, segment.Count);
ushort count = 0;
bool success = true;
count += sizeof(ushort); //추후 패킷의 사이즈가 들어갈 공간을 비워둠
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), (ushort)PacketID.PlayerInfoReq);
count += sizeof(ushort);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), this.playerID);
count += sizeof(long);
// player name
ushort nameLength = (ushort)Encoding.Unicode.GetBytes(this.name, 0, this.name.Length, segment.Array, segment.Offset + count + sizeof(ushort));
// string 바이트의 길이가 들어갈 2바이트를 건너 뛰고 string 데이터를 먼저 바이트에 써넣고,
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), nameLength);
// 그 후 계산된 string의 바이트 길이를 앞에 바이트로 써넣는다.
count += sizeof(ushort);
count += nameLength;
// skill info list size
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), (ushort)skills.Count);
count += sizeof(ushort);
// skill info list
for (int i = 0; i < skills.Count; i++)
{
success &= skills[i].Write(s, ref count);
}
success &= BitConverter.TryWriteBytes(s, count);
if (success == false)
{
return null;
}
return SendBufferHelper.Close(count);
}
위 방법은 가장 쉬운 방법으로 구현되었고, 이를 최적화 하기 위해서
프로토 버프나 플랫버퍼 라이브러리를 사용할 수 있음