SendBuffer
이전에 만든 RecvBuffer에 이어서 SendBuffer를 만들어 보자
public class SendBuffer
{
byte[] _buffer;
int _usedSize = 0;
public int FreeSize { get { return _buffer.Length - _usedSize; } }
public SendBuffer(int chunkSize)
{
_buffer = new byte[chunksize];
}
public ArraySegment<byte> Open(int reserveSize)
{
if(reserveSize > FreeSize)
return null;
return new ArraySegment<byte>(_buffer, _usedSize, reserveSize);
}
public ArraySegment<byte> Close(int usedSize)
{
ArraySegment<byte> segment = new ArraySegment<byte>(_buffer,_usedSize,usedSize);
_usedSize += usedSize;
return segment;
}
}
[/][/] [/][u] [/][/] [/][/] [/][/]
int _usedSize = 0;
FreeSize : 남은 공간
Open
2-1. 최대 할당 크기
2-2. 남은 공간이 남아있으면 reserveSize만큼 할당
2-3. 예약공간(reserveSize)보다 남은 공간(FreeSize)가 적으면 buffer은 고갈된 것이니 null 리턴
Close
3-1. 실제 내가 사용한 사이즈
3-2. 위의 Open에서 3바이트를 할당했지만 실제로는 2바이트만 사용했으면 남은 공간을 반환
3-3. 유효범위 리턴
public class SendBufferHelper
{
//전역으로 선언하면 SendBuffer은 처음 할당한 크기에서 사용이 가능하면 재사용을 할 건데
//멀티 쓰레드환경에서는 경합이 될것이다.
//그래서 이전에 배운 전역이지만 나의 쓰레드에서 고유하게 사용가능한 전역 선언방법
public static ThreadLocal<SendBuffer> CurrentBuffer = new ThreadLocal<SendBuffer>(() => { return null; });
public static int ChunkSize { get; set; } = 4096 * 100;
public static ArraySegment<byte> Open(int reserveSize)
{
if (CurrentBuffer.Value == null)
{
//null이면 한번도 사용하지 않은 상태이니 생성
CurrentBuffer.Value = new SendBuffer(ChunkSize);
}
if (CurrentBuffer.Value.FreeSize < reserveSize)
{
//지금 남은 공간이 예약공간보다 적으면 새로운 버퍼로 갈아끼움
CurrentBuffer.Value = new SendBuffer(ChunkSize);
}
//여기까지 조건문을 통과했으면 남은공간이 있다는거니까 Open
return CurrentBuffer.Value.Open(reserveSize);
}
public static ArraySegment<byte> Close(int usedSize)
{
return CurrentBuffer.Value.Close(usedSize);
}
}
사용 코드 흐름 ( 완벽하지 않음)
//클라이언트 -> 서버
class Packet()
{
public ushort size;
public ushort packetId;
}
class PlayerInfoReq : Packet
{
public long playerId;
}
class ServerSession : Session
{
public override void OnConnected(EndPoint endPoint)
{
Console.WriteLine($"OnConnected ! {endPoint}");
PlayerInfoReq packet = new PlayerInfoReq() {packetId = (ushort)PacketID.PlayerInfoReq, playerId = 1001};
ArraySegment<byte> s = SendBufferHelper.Open(4096);
ushort count = 0;
bool success = true;
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), packet.packetId);
count += 2;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset + count, s.Count - count), packet.playerId);
count += 8;
success &= BitConverter.TryWriteBytes(new Span<byte>(s.Array, s.Offset, s.Count), count);
ArraySegment<byte> sendBuff = SendBufferHelper.Close(count);
if(success)
Send(sendBuff);
}
}