패킷 자동화 처리 알아보러 가기
네트워크프로그래밍 - 패킷 자동화 처리(TryWriteBytes,c#에서 포인터 사용하는 법)
패킷작업하기 서버, 클라이언트에 이 정보가 다 있어야 한다. class Packet { public short size; public short packetId; } class PlayerInfoReq : Packet { public long playerId; } class PlayerInfoOk : Packet { public int hp; public int atta
code-piggy.tistory.com
객체지향 방법 사용하기
패킷을 만든 다음에 해야되는 부분이 너무 많다. 그러므로 밀어 넣어주는 부분을 따로 빼서 객체지향 방법을 사용하는 것이 좋다.
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 |
댓글