VisualStudio/C#서버

[C#서버] BitConverter 사용법 - ArraySegment<byte>, Span, Slice

usingsystem 2022. 10. 31. 10:36
728x90

BitConverter

BitConverter는 데이터 직렬화/역직렬화를 위한 강력한 도구입니다.

기본 사용법

1. 문자열 → 배열 변환

BitConverter.GetBytes(문자열);

2. 배열의 특정 위치 데이터 → 문자열 변환

  • ushort 데이터 추출 시, 2바이트 크기만큼 읽어옵니다.
BitConverter.ToUInt16(읽을배열, 읽을위치);

3. ReadOnlySpan 활용

  • 읽기 전용 데이터를 처리하며 안전성을 보장합니다.
BitConverter.ToUInt16(new ReadOnlySpan<byte>(...));

예제

using System;

public class Packet
{
    public ushort size; // 패킷 크기
    public ushort packetId; // 패킷 ID
}

internal class Program
{
    static void Main(string[] args)
    {
        // 1. 패킷 데이터 생성
        Packet packet = new Packet { size = 10, packetId = 5 };

        // 2. 데이터 저장용 배열 생성
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

        // 3. 데이터를 바이트 배열로 변환
        byte[] sizeBytes = BitConverter.GetBytes(packet.size);
        byte[] packetIdBytes = BitConverter.GetBytes(packet.packetId);

        // 4. 변환된 데이터를 버퍼에 복사
        Array.Copy(sizeBytes, 0, buffer.Array, buffer.Offset, sizeBytes.Length);
        Array.Copy(packetIdBytes, 0, buffer.Array, buffer.Offset + sizeBytes.Length, packetIdBytes.Length);

        // 5. 버퍼에서 데이터 읽기
        ushort extractedSize = BitConverter.ToUInt16(buffer.Array, 0);
        ushort extractedPacketId = BitConverter.ToUInt16(buffer.Array, 2);

        // 결과 출력
        Console.WriteLine($"Extracted Size: {extractedSize}, Packet ID: {extractedPacketId}");
    }
}

 

BitConverter.TryWriteBytes 활용

  • 배열 생성 없이 직렬화된 데이터를 특정 위치에 바로 복사
  • Array.Copy 불필요
  • 주의: .NET Core 이상에서만 사용 가능, .NET Framework에서는 지원되지 않음
using System;

public class Packet
{
    public ushort size; // 패킷 크기
    public ushort packetId; // 패킷 ID
}

internal class Program
{
    static void Main(string[] args)
    {
        // 1. 패킷 데이터 생성
        Packet packet = new Packet { size = 10, packetId = 5 };

        // 2. 버퍼 생성 (ArraySegment)
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

        // 3. Span을 통해 버퍼 관리
        Span<byte> spanBuffer = new Span<byte>(buffer.Array, buffer.Offset, buffer.Count);

        // 4. 데이터를 버퍼에 직렬화
        bool success = true;
        success &= BitConverter.TryWriteBytes(spanBuffer.Slice(0), packet.size); // size 기록
        success &= BitConverter.TryWriteBytes(spanBuffer.Slice(sizeof(ushort)), packet.packetId); // packetId 기록

        if (!success)
        {
            Console.WriteLine("Data serialization failed.");
            return;
        }

        // 5. 버퍼에서 데이터 역직렬화
        ushort extractedSize = BitConverter.ToUInt16(buffer.Array, 0);
        ushort extractedPacketId = BitConverter.ToUInt16(buffer.Array, sizeof(ushort));

        // 결과 출력
        Console.WriteLine($"Extracted Size: {extractedSize}, Packet ID: {extractedPacketId}");
    }
}

 

Slice를 활용한 범위 제한

Slice 메서드를 사용해 특정 범위 데이터를 처리할 수 있습니다.

using System;

public class Packet
{
    public ushort size; // 패킷 크기
    public ushort packetId; // 패킷 ID
}

internal class Program
{
    static void Main(string[] args)
    {
        // 1. 패킷 데이터 생성
        Packet packet = new Packet { size = 10, packetId = 5 };

        // 2. 데이터 저장용 버퍼 생성
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

        // 3. 데이터를 Span에 기록
        Span<byte> spanBuffer = new Span<byte>(buffer.Array, buffer.Offset, buffer.Count);
        BitConverter.TryWriteBytes(spanBuffer.Slice(0), packet.size);
        BitConverter.TryWriteBytes(spanBuffer.Slice(sizeof(ushort)), packet.packetId);

        // 4. ReadOnlySpan으로 데이터 읽기
        ReadOnlySpan<byte> readOnlySpan = new ReadOnlySpan<byte>(buffer.Array, buffer.Offset, buffer.Count);
        ushort extractedSize = BitConverter.ToUInt16(readOnlySpan.Slice(0));
        ushort extractedPacketId = BitConverter.ToUInt16(readOnlySpan.Slice(sizeof(ushort)));

        // 결과 출력
        Console.WriteLine($"Extracted Size: {extractedSize}, Packet ID: {extractedPacketId}");
    }
}
728x90