반응형
패킷 자동화 처리 알아보러 가기
객체지향 방법 사용하기
패킷을 만든 다음에 해야되는 부분이 너무 많다. 그러므로 밀어 넣어주는 부분을 따로 빼서 객체지향 방법을 사용하는 것이 좋다.
1. Write
01 기존 코드
ArraySegment<byte> openSegment = SendBufferHandler.Open(4096);
bool success = true;
ushort count = 0;
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset + count, openSegment.Count - count), packet.packetId);
ㅌcount += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset + count, openSegment.Count-count), packet.playerId);
count += 8;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset, openSegment.Count),count);
ArraySegment<byte> sendBuff = SendBufferHandler.Close(count);
02 인터페이스 설정
Write : 직렬화 작업을 수행
Read : 역직렬화 작업을 수행
public abstract class Packet
{
public ushort size;
public ushort packetId;
public abstract ArraySegment<byte> Write();
public abstract void Read(ArraySegment<byte> s);
}
03 Write, Read메서드 구현 및 생성자 설정
packetId는 네트워크 통신에서 패킷의 종류를 식별하는데 사용된다. 이를 생성자가 호출될때마다 packetId를 설정되도록 한다.
class PlayerInfoReq : Packet
{
public long playerId;
public PlayerInfoReq()
{
this.packetId = (ushort)PacketID.PlayerInfoReq;
}
public override void Read(ArraySegment<byte> s)
{
}
public override ArraySegment<byte> Write()
{
}
}
04 Write메서드
public override ArraySegment<byte> Write()
{
ArraySegment<byte> openSegment = SendBufferHandler.Open(4096);
bool success = true;
ushort count = 0;
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset + count, openSegment.Count - count), this.packetId);
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset + count, openSegment.Count - count), this.playerId);
count += 8;
success &= BitConverter.TryWriteBytes(new Span<byte>(openSegment.Array, openSegment.Offset, openSegment.Count), count);
return SendBufferHandler.Close(count);
}
기존 코드와의 차이
this.packet, this.playerId와 같이 현재 클래스 내의 변수를 사용하여 데이터에 접근한다.
ArraySegemt
public static bool operator ==(ArraySegment<T> a, ArraySegment<T> b);
ArraySegemt<T>의 두개의 구조체를 비교해서 동일한지 여부를 확인할 수 있는 메서드이다. 만약 내용과 길이가 같다면 true를 반환하고 아닐 경우 false를 반환한다.
이를 이용해서 데이터 변환작업의 성공여부에 대한 추가 처리할 수 있다.
if (success == false)
{
return null;
}
05 최종 결과
packet객체의 Write메서드를 호출하고 데이터를 ArraySegement<byte>형식으로 받아온다.
ArraySegment<byte> s = packet.Write();
if (s != null)
Send(s);
2. Read
01 기존 코드
switch((PacketID)id)
{
case PacketID.PlayerInfoReq:
{
long playerid = BitConverter.ToUInt16(buffer.Array, buffer.Offset + count);
count += 8;
Console.WriteLine($"PlayerInfoReq: {playerid}");
}
break;
}
02 Read메서드
ArraySegment<byte>에서 데이터를 역직렬화 한 다음 playerId 필드에 할당하는 작업을 수행
public override void Read(ArraySegment<byte> openSegment)
{
ushort count = 0;
//ushort size = BitConverter.ToUInt16(openSegment.Array, openSegment.Offset);
count += 2;
//ushort id = BitConverter.ToUInt16(openSegment.Array, openSegment.Offset + count);
count += 2;
this.playerId = BitConverter.ToUInt16(openSegment.Array, openSegment.Offset + count);
count += 8;
}
03 최종 결과
원래 직접 역직렬화하여 값을 얻어왔는데, 이제는 PlayerInfoReq클래스의 인스턴스를 생성화고 Read메서드를 호출하여 역직렬화 작업을 수행한다.
switch((PacketID)id)
{
case PacketID.PlayerInfoReq:
{
PlayerInfoReq p = new PlayerInfoReq();
p.Read(buffer);
Console.WriteLine($"PlayerInfoReq: {p.playerId}");
}
break;
}
3. 결과
참고 : 본 내용은 MMORPG PART4 강의를 수강하여 작성하였습니다.
https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part4
반응형
'cs공부 > 네트워크프로그래밍' 카테고리의 다른 글
네트워크프로그래밍 - ENCODING(ASCII,UTF-8,UTF-16) (0) | 2023.08.08 |
---|---|
네트워크프로그래밍 - packetId와 size에 대한 이슈(client의 거짓말, ReadOnlySpan) (0) | 2023.08.07 |
네트워크프로그래밍 - 직렬화(Serialization), 역직렬화(Deserialization), Session, 패킷 작업 정의 (0) | 2023.08.03 |
네트워크프로그래밍 - 패킷 자동화 처리(TryWriteBytes,c#에서 포인터 사용하는 법) (0) | 2023.08.02 |
네트워크 프로그래밍 - PacketSession (0) | 2023.07.31 |
댓글