Notice
Recent Posts
Recent Comments
Link
bdfgdfg
[C# 서버] ArraySegment - 버퍼 부분 참조 본문
반응형
C++에서는 포인터를 쓰면 간단하게 해결할 문제이지만 C#은 버퍼의 인덱스부터 ~ 어느 인덱스까지를 사용하는건 어렵다.
이때 사용할 수 있는게 ArraySegment.
네트워크 송수신에서 데이터를 주고 받기 위해 정의된 패킷타입이 다음과 같다고 보자.
// [패킷 프로토콜][패킷 길이][데이터 필드]
// [2byte(Protocol)][2byte(Length)][N-byte(Data Field)]
해당 데이터를 해석하기 위한 별도의 클래스나 툴이없다면 직접 부분참조해서 읽어와야 한다.
class Program
{
static void Main(string[] args)
{
ArraySegment<byte> packetBuffer = new ArraySegment<byte>(new byte[1024], 0, 1024);
int writePos = 0;
int readPos = 0;
const ushort gameStartProtocol = 1234;
int[] data = new int[3] { 10, 20, 30 }; // Data Field
// 직렬화
// 프로토콜
Array.Copy(BitConverter.GetBytes(gameStartProtocol), 0, packetBuffer.Array, packetBuffer.Offset + writePos, sizeof(ushort));
writePos += sizeof(ushort);
// 패킷 길이. (헤더 + 데이터 필드)
Array.Copy(BitConverter.GetBytes(4 + data.Length * sizeof(int)), 0, packetBuffer.Array, packetBuffer.Offset + writePos, sizeof(ushort));
writePos += sizeof(ushort);
// 데이터 필드
Array.Copy(BitConverter.GetBytes(data[0]), 0, packetBuffer.Array, packetBuffer.Offset + writePos, sizeof(int));
writePos += sizeof(int);
Array.Copy(BitConverter.GetBytes(data[1]), 0, packetBuffer.Array, packetBuffer.Offset + writePos, sizeof(int));
writePos += sizeof(int);
Array.Copy(BitConverter.GetBytes(data[2]), 0, packetBuffer.Array, packetBuffer.Offset + writePos, sizeof(int));
writePos += sizeof(int);
//역직렬화.
//프로토콜
ushort protocolID = BitConverter.ToUInt16(packetBuffer.Array,readPos);
readPos += sizeof(ushort);
ushort packetLen = BitConverter.ToUInt16(packetBuffer.Array, readPos);
readPos += sizeof(ushort);
int data1 = BitConverter.ToInt32(packetBuffer.Array, readPos);
readPos += sizeof(int);
int data2 = BitConverter.ToInt32(packetBuffer.Array, readPos);
readPos += sizeof(int);
int data3 = BitConverter.ToInt32(packetBuffer.Array, readPos);
readPos += sizeof(int);
Console.WriteLine($"프로토콜 : {protocolID} 패킷 길이 : {packetLen}");
Console.WriteLine($"데이터 : {data1},{data2},{data3}");
}
}
간단하게 ArraySegment를 이용해보았다. 사실은 ArraySegment가 아니더라도 단순히 byte배열을 이용해도 위의 코드는 처리가 가능하다.
단 ArraySegment의 가장 강력한점은 밑과 같다.
ArraySegment<byte> array = new ArraySegment<byte>(packetBuffer.Array, 0, sizeof(ushort));
packetBuffer의 해당 인덱스부터 시작해 할당한 길이만큼의 버퍼를 가져올 수 있는 것.(원본의 버퍼)
실제 2바이트만큼 할당하였고, Count가 2인것을 알 수 있음.
또한 2번째인자를 0으로 준것은 packetBuffer의 0번째 인덱스부터 길이 2만큼의 부분 버퍼를 가져온 것인데.
이 시작 인덱스를 달리하여 원하는 길이만큼의 버퍼도 당연히 얻어올 수 있다.
ArraySegment<byte> array = new ArraySegment<byte>(packetBuffer.Array, 2, sizeof(ushort));
Offset이 2인모습.
즉. packetBuffer의 인덱스 2부터 3까지는 패킷의 길이를 나타내는데, 위를 활용하면.
ArraySegment<byte> array = new ArraySegment<byte>(packetBuffer.Array, packetBuffer.Offset + 2, sizeof(ushort));
Console.WriteLine(BitConverter.ToUInt16(array.Array,array.Offset));
위와 같이 적용가능하다.
반응형
Comments