class ServerSession : Session
{
//...
public override void OnConnected(EndPoint endPoint)
{
Console.WriteLine($"OnConnected : {endPoint}");
PlayerInfoReq packet = new PlayerInfoReq() { size = 4, packetId = (ushort)PacketID.PlayerInfoReq, playerId = 1001 };
// 아래와 같이 번거로운 작업을 좀 간단히 해보자
// 보낸다
for (int i = 0; i < 5; i++)
{
ArraySegment<byte> s = SendBufferHelper.Open(4096);
//byte[] size = BitConverter.GetBytes(packet.size);
//byte[] packetId = BitConverter.GetBytes(packet.packetId);
//byte[] playerId = BitConverter.GetBytes(packet.playerId);
ushort size = 0;
bool success = true;
size += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), packet.packetId);
size += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), packet.playerId);
size += 8;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), size);
ArraySegment<byte> sendBuff = SendBufferHelper.Close(size);
if (success)
Send(sendBuff);
}
}
개선해보자
// Packet내에서 어떻게 처리할지 정의
class PlayerInfoReq : Packet
{
public long playerId;
public PlayerInfoReq()
{
this.playerId = (ushort)PacketID.PlayerInfoReq;
}
public override ArraySegment<byte> Write()
{
ArraySegment<byte> s = SendBufferHelper.Open(4096);
ushort size = 0;
bool success = true;
size += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), this.packetId);
size += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + size, s.Count - size), this.playerId);
size += 8;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), size);
if (success == false)
return null;
return SendBufferHelper.Close(size);
}
public override void Read(ArraySegment<byte> s)
{
ushort count = 0;
count += 2; // size
count += 2; // id
this.playerId = BitConverter.ToInt64(s.Array, s.Offset + count);
count += 8;
}
}
public override void OnRecvPacket(ArraySegment<byte> buffer)
{
int pos = 0;
ushort size = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
pos += 2;
ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + pos);
pos += 2;
// TODO
switch ((PacketID)id)
{
case PacketID.PlayerInfoReq:
{
PlayerInfoReq p = new PlayerInfoReq();
p.Read(buffer);
Console.WriteLine($"PlayerInfoReq: {p.playerId}");
}
좀 더 개선해보자면
public override void Read(ArraySegment<byte> s)
{
ushort count = 0;
count += 2; // size
count += 2; // id
// READ시에 size값을 참조하지 않고 Read하기에 악의적 데이터가 들어와도 검열할 방법이 없음
this.playerId = BitConverter.ToInt64(s.Array, s.Offset + count);
count += 8;
}
public override void Read(ArraySegment<byte> s)
{
ushort count = 0;
count += 2; // size
count += 2; // id
// 아래와 같이 범위를 제한할 수 있음.
this.playerId = BitConverter.ToInt64(new ReadOnlySpan<byte>(s.Array, s.Offset + count, s.Count - count));
count += 8;
}