(C#) Serialization [1]
포스트
취소

(C#) Serialization [1]

나중에 직렬화 관련 코드는 매우 많이 사용되기 때문에 자동화를 해주는 것이 좋다.

이번 글은 자동화를 만들기 위해 어떤식으로 구현할지 미리 인터페이스를 짜본다.

💻 코드

패킷 추가

테스트할 임시 패킷을 추가한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Packet
{
    public ushort size;
    public ushort packetId;
}

// 유저 확인용으로 보내줄 패킷
class PlayerInfoReq : Packet
{
    public long playerId;
}

// 유저 확인될 시 보내줄 패킷
class PlayerInfoOk : Packet
{
    public int hp;
    public int attack;
}

// 패킷 ID
public enum PacketID
{
    PlayerInfoReq = 1,
    PlayerInfoOk = 2,
}


ServerClientSession Class를 만들어주고, ClientServerSession을 만들어준다.

각 Session은 서로의 도우미 역할로 어떤식으로 보내고 받는지 도와줄 것이다.

Client

BitConverter.TryWriteBytes를 통해 버퍼안에 데이터를 가져올 수 있다.

count로 다음 위치 확인 및 사이즈를 체크해준다.

만약 버퍼안에 데이터가 없는 경우 successfalse를 뱉으므로 Send할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
namespace DummyClient
{
    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
            };

            // 4096 버퍼 사용하기 (이름이 길어 segment -> s)
            ArraySegment<byte> s = SendBufferHelper.Open(4096);

            bool success = true;
            ushort count = 0;

            // [직렬화 시작]
            // size 공간 +
            count += 2;

            // packetId 공간 +
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), packet.packetId);
            count += 2;

            // playerId 공간 +
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), packet.playerId);
            count += 8;

            // 총 사이즈는 다 넣어야 알 수 있기 때문에 마지막에 넣기 
            success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), count);

            // 얼마나 썼는지 알려주기
            ArraySegment<byte> sendBuff = SendBufferHelper.Close(count);

            // 조립에 성공하면 전송
            if (success)
                Send(sendBuff);
        }
    }
}

Server

sizepacketId는 정해져 있으니 먼저 구현하고,

그 다음 버퍼에는 전달 받을 데이터가 들어있으니 switch를 사용해 확인한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace Server
{
    class ClientSession : PacketSession
    {
        public override void OnRecvPacket(ArraySegment<byte> buffer)
        {
            // [역직렬화 시작]
            int count = 0;
            ushort size = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
            count += 2;
            ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + count);
            count += 2;

            switch ((PacketID)id)
            {
                case PacketID.PlayerInfoReq:
                    {
                        long playerId = BitConverter.ToInt64(buffer.Array, buffer.Offset + count);
                        count += 8;

                        Console.WriteLine($"PlayerInfoReq : {playerId}");
                    }
                    break;
            }
        }
    }
}

BitConverter.TryWriteBytes가 선언이 안된다면

구글링을 좀 하다가 프레임워크를 추가 적용하는 방법을 몰라서 프로젝트를 새로 만들고

  1. 프로젝트 우클릭 -> 속성 -> 대상 프레임워크 확인
  2. 대상 프레임워크.Net Core가 아닐 경우 바꿔주도록 한다.
  3. 만약 .Net Core가 없다면 프로젝트를 다시 만들어서 프레임워크가 없는 콘솔창을 선택해 만들어준다.
  4. 원래 사용하던 코드를 옮겨준다.

프레임워크 없는 콘솔창 선택

프젝만들기

프레임워크 .Net Core 설정

프레임워크


💡 참고

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.