C#/네트워크

[c#][서버] PacketSession

goliot 2024. 6. 7. 16:49
반응형

패킷 조립

  • 그냥 byte 배열을 보내는 것이 아닌, Size, packetId등을 가진 패킷을 조립해서 넘겨보자
namespace Server
{
    class Packet
    { //최대한 크기를 작게 보내자
        public ushort size; //2 Byte
        public ushort packetId;
    }
    
    class GameSession : PacketSession
    {
        //OnRecv가 PacketSession에서 sealed가 됐으므로, 재정의 불가
        //abstract OnRecvPacket을 정의하여 사용
        public override void OnRecvPacket(ArraySegment<byte> buffer)
        {
            ushort size = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
            ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + 2);
            Console.WriteLine($"RecvPacketId: {id}, Size: {size}");
        }
    }
}

public abstract class PacketSession : Session
{
    public static readonly int HeaderSize = 2;

    //sealed를 쓰면 내가 봉인을 했다는 의미
    //[size(2)][packetId(2)][...][size(2)][packetId(2)][...] 
    public sealed override int OnRecv(ArraySegment<byte> buffer)
    {
        int processLen = 0;

        while(true)
        {
            //최소한 헤더는 파싱할 수 있는지 확인(size-2)
            if (buffer.Count < HeaderSize)
                break;

            //패킷이 완전체로 도착했는지
            ushort dataSize = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
            if (buffer.Count < dataSize)
                break;

            //여기까지 왔으면 패킷 조립 가능
            OnRecvPacket(new ArraySegment<byte>(buffer.Array, buffer.Offset, dataSize));

            processLen += dataSize;
            buffer = new ArraySegment<byte>(buffer.Array, buffer.Offset + dataSize, buffer.Count - dataSize); //버퍼 옮기기
        }

        return processLen;
    }

    public abstract void OnRecvPacket(ArraySegment<byte> buffer);
}

 

반응형

'C# > 네트워크' 카테고리의 다른 글

[c#][서버] Unicode & Encoding / UTF8 vs UTF16  (0) 2024.06.09
[c#][서버] Serialization  (0) 2024.06.09
[c#][서버] RecvBuffer, SendBuffer  (1) 2024.06.07
[c#][서버] TCP vs UDP  (0) 2024.06.07
[c#][서버] Connector  (0) 2024.06.07