(C# : Server) 27. Serialization - 2

Posted by : at

Category : Charp-Server



class ServerSession : Session
{
    //...
    public override void OnConnected(EndPoint endPoint)
    {
        Console.WriteLine($"OnConnected : {endPoint}");

        PlayerInfoReq packet = new PlayerInfoReq() { size = 4, packetId = (ushort)PacketID.PlayerInfoReq, playerId = 1001 };

        // 아래와 같이 번거로운 작업을 좀 간단히 해보자
        // 보낸다
        for (int i = 0; i < 5; i++)
        {
            ArraySegment<byte> s = SendBufferHelper.Open(4096);
            //byte[] size = BitConverter.GetBytes(packet.size);
            //byte[] packetId = BitConverter.GetBytes(packet.packetId);
            //byte[] playerId = BitConverter.GetBytes(packet.playerId);

            ushort size = 0;
            bool success = true;
        
            size += 2;
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), packet.packetId);
            size += 2;
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), packet.playerId);
            size += 8;
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), size);

            ArraySegment<byte> sendBuff = SendBufferHelper.Close(size);

            if (success)
                Send(sendBuff);
        }
    }

개선해보자

// Packet내에서 어떻게 처리할지 정의
class PlayerInfoReq : Packet
{
    public long playerId;

    public PlayerInfoReq()
    {
        this.playerId = (ushort)PacketID.PlayerInfoReq;
    }

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

        ushort size = 0;
        bool success = true;

        size += 2;
        success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), this.packetId);
        size += 2;
        success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), this.playerId);
        size += 8;
        success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), size);

        if (success == false)
            return null;

        return SendBufferHelper.Close(size);
    }

    public override void Read(ArraySegment<byte> s)
    {
        ushort count = 0;
        count += 2; // size
        count += 2; // id
        this.playerId = BitConverter.ToInt64(s.Array, s.Offset + count);
        count += 8;
    }
}
public override void OnRecvPacket(ArraySegment<byte> buffer)
{
    int pos = 0;

    ushort size = BitConverter.ToUInt16(buffer.Array, buffer.Offset); 
    pos += 2;
    ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + pos);
    pos += 2;

    // TODO
    switch ((PacketID)id)
    {
        case PacketID.PlayerInfoReq:
            {
                PlayerInfoReq p = new PlayerInfoReq();
                p.Read(buffer);
                Console.WriteLine($"PlayerInfoReq: {p.playerId}");
            }

좀 더 개선해보자면

public override void Read(ArraySegment<byte> s)
{
    ushort count = 0;
    count += 2; // size
    count += 2; // id
    // READ시에 size값을 참조하지 않고 Read하기에 악의적 데이터가 들어와도 검열할 방법이 없음
    this.playerId = BitConverter.ToInt64(s.Array, s.Offset + count);
    count += 8;
}
public override void Read(ArraySegment<byte> s)
{
    ushort count = 0;
    count += 2; // size
    count += 2; // id
    
    // 아래와 같이 범위를 제한할 수 있음.
    this.playerId = BitConverter.ToInt64(new ReadOnlySpan<byte>(s.Array, s.Offset + count, s.Count - count));
    count += 8;
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links