C#/네트워크 관련
Serialization #2
tmd1
2024. 11. 26. 23:27
using ServerCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
public abstract class Packet
{
public ushort size;
public ushort packetId;
public abstract ArraySegment<byte> Write();
public abstract void Read(ArraySegment<byte> s);
}
class PlayerInfoReq : Packet
{
public long playerId;
public PlayerInfoReq()
{
this.packetId = (ushort)PacketID.PlayerInfoReq;
}
public override void Read(ArraySegment<byte> s)
{
ushort count = 0;
//ushort size = BitConverter.ToUInt16(s.Array, s.Offset);
count += 2;
//ushort id = BitConverter.ToUInt16(s.Array, s.Offset + count);
count += 2;
// TODO: 크기 넘어가면 exception 난다는데 이해하고 주석 수정
// size, id 다음부터 읽는데 Write해서 보내준 크기 - 헤더정보를 제외했을 때
// 읽어올 데이터의 크기만큼의 공간이 존재하지 않는다면 exception
this.playerId = BitConverter.ToInt64(new ReadOnlySpan<byte>(s.Array, s.Offset + count, s.Count - count));
count += 8;
}
public override ArraySegment<byte> Write()
{
ArraySegment<byte> s = SendBufferHelper.Open(4096);
ushort count = 0;
bool success = true;
// s.Count 보다 넣어주는게 크면 false
// TrtWriteBytes 이용해서 곧바로 ArraySement에 넣어줌
count += 2; // size 크기 미리 넣음(unshort)
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), this.packetId);
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), this.playerId);
count += 8;
// packet의 size 즉 count는 나중에 확정되므로 마지막에 보내줌
// count의 저장되어 있는 값은 패킷의 size(=12)고 size의 크기는 2(unshort)임
// count의 타입 유의 - count 타입이 int면 4 byte이므로 값이 덮어씌워 질 수 있음
// 물론 지금은 하드코딩이라서 그런거지만..
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), count);
if (success == false)
return null;
return SendBufferHelper.Close(count);
}
}
public enum PacketID
{
PlayerInfoReq = 1,
PlayerInfoOk = 2
}
class ClientSession : PacketSession
{
public override void OnConnected(EndPoint endPoint)
{
Console.WriteLine($"OnConnected : {endPoint}");
Thread.Sleep(5000);
Disconnect();
}
public override void OnRecvPacket(ArraySegment<byte> buffer)
{
ushort 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:
{
PlayerInfoReq q = new PlayerInfoReq();
q.Read(buffer);
Console.WriteLine($"PlayerInfoReq : {q.playerId}");
break;
}
}
Console.WriteLine($"ReceivePacketId : {id}, Size : {size}");
}
public override void OnDisconnect(EndPoint endPoint)
{
Console.WriteLine($"OnDisconnected : {endPoint}");
}
public override void OnSend(int numOfBytes)
{
Console.WriteLine($"Transferred bytes: {numOfBytes}");
}
}
}
using ServerCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace DummyClient
{
public abstract class Packet
{
public ushort size;
public ushort packetId;
public abstract ArraySegment<byte> Write();
public abstract void Read(ArraySegment<byte> s);
}
class PlayerInfoReq : Packet
{
public long playerId;
public PlayerInfoReq()
{
this.packetId = (ushort)PacketID.PlayerInfoReq;
}
public override void Read(ArraySegment<byte> s)
{
ushort count = 0;
//ushort size = BitConverter.ToUInt16(s.Array, s.Offset);
count += 2;
//ushort id = BitConverter.ToUInt16(s.Array, s.Offset + count);
count += 2;
// TODO: 크기 넘어가면 exception 난다는데 이해하고 주석 수정
// size, id 다음부터 읽는데 Write해서 보내준 크기 - 헤더정보를 제외했을 때
// 읽어올 데이터의 크기만큼의 공간이 존재하지 않는다면 exception
this.playerId = BitConverter.ToInt64(new ReadOnlySpan<byte>(s.Array, s.Offset + count, s.Count - count));
count += 8;
}
public override ArraySegment<byte> Write()
{
ArraySegment<byte> s = SendBufferHelper.Open(4096);
ushort count = 0;
bool success = true;
// s.Count 보다 넣어주는게 크면 false
// TrtWriteBytes 이용해서 곧바로 ArraySement에 넣어줌
count += 2; // size 크기 미리 넣음(unshort)
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), this.packetId);
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), this.playerId);
count += 8;
// packet의 size 즉 count는 나중에 확정되므로 마지막에 보내줌
// count의 저장되어 있는 값은 패킷의 size(=12)고 size의 크기는 2(unshort)임
// count의 타입 유의 - count 타입이 int면 4 byte이므로 값이 덮어씌워 질 수 있음
// 물론 지금은 하드코딩이라서 그런거지만..
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), count);
if (success == false)
return null;
return SendBufferHelper.Close(count);
}
}
public enum PacketID
{
PlayerInfoReq = 1,
PlayerInfoOk = 2
}
class ServerSession : Session
{
public override void OnConnected(EndPoint endPoint)
{
Console.WriteLine($"OnConnected : {endPoint}");
// 패킷을 최종적으로 보내기 전 까지는 사이즈를 알 수 없음
PlayerInfoReq packet = new PlayerInfoReq() { playerId = 1001 };
{
ArraySegment<byte> sendBuff = packet.Write();
if(sendBuff != null)
Send(sendBuff);
}
}
public override void OnDisconnect(EndPoint endPoint)
{
Console.WriteLine($"OnDisconnected : {endPoint}");
}
public override int OnRecv(ArraySegment<byte> buffer)
{
string recvData = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
Console.WriteLine($"[From Server] {recvData}");
return buffer.Count;
}
public override void OnSend(int numOfBytes)
{
Console.WriteLine($"Transferred bytes: {numOfBytes}");
}
}
}