🌞 패킷작업을 위한 RecvBuffer
패킷 작업을 위한 초석단계이다. ( 아직 왜 쓰는지는 모르겠다.. 다음 수업들을 들어봐야알듯)
기존에는 Session의 Start메소드에서 아규먼트의 SetBuffer를 통하여 RecvBuffer를 등록해주었다.
이 작업을 통해 달라진 점은 RecvBuffer 클래스를 만들어서 ArraySegment로 충분히 큰 buffer를 하나 만들어서, 그 buffer 하나를 이용하여 데이터를 쓰고 읽게끔 만들어 준 것이다.
눈에 들어왔던 점은 ReadSegement와 WriteSegment로 각각 RecvBuffer 클래스의 인스턴스 변수로 ArraySegment 타입인데, 각각 Offset과 Count의 값을 다르게 설정하여 쉽게 Read, Write 부분을 찾을 수 있게 한 부분이 눈에 가장 들어왔다.
using System;
using System.Collections.Generic;
using System.Text;
namespace ServerCore
{
class RecvBuffer
{
ArraySegment<byte> _buffer;
int _readPos;
int _writePos;
public RecvBuffer(int bufferSize)
{
_buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
}
public int DataSize { get { return _writePos - _readPos; } }
public int FreeSize { get { return _buffer.Count - _writePos; } }
public ArraySegment<byte> ReadSegment
{
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _readPos, DataSize); }
}
public ArraySegment<byte> WriteSegment
{
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _writePos, FreeSize); }
}
public void Clean()
{
int dataSize = DataSize;
if( dataSize == 0)
{
_readPos = _writePos = 0;
}
else
{
Array.Copy(_buffer.Array, _buffer.Offset + _readPos, _buffer.Array, _buffer.Offset, dataSize);
_readPos = 0;
_writePos = dataSize;
}
}
public bool OnRead(int numOfBytes)
{
if (numOfBytes > DataSize)
return false;
_readPos += numOfBytes;
return true;
}
public bool OnWrite(int numOfBytes)
{
if (numOfBytes > FreeSize)
return false;
_writePos += numOfBytes;
return true;
}
}
}
void RegisterRecv()
{
_recvBuffer.Clean();
ArraySegment<byte> segment = _recvBuffer.WriteSegment;
_recvArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);
bool pending = _socket.ReceiveAsync(_recvArgs);
if (pending == false)
OnRecvCompleted(null, _recvArgs);
}
void OnRecvCompleted(object obj, SocketAsyncEventArgs args)
{
if(args.BytesTransferred != 0 && args.SocketError==SocketError.Success)
{
try
{
if(_recvBuffer.OnWrite(args.BytesTransferred)== false)
{
Disconnect();
return;
}
int processLen = OnRecv(_recvBuffer.ReadSegment);
if(processLen < 0 || _recvBuffer.DataSize < processLen)
{
Disconnect();
return;
}
if(_recvBuffer.OnRead(processLen) == false)
{
Disconnect();
return;
}
RegisterRecv();
}
catch(Exception e)
{
Console.WriteLine($"OnRecvCompleted Failed {e}");
}
}
else
{
Disconnect();
}
}
}
기존에는 Start 메소드에서 SetBuffer를 해주었다면, 이제부터는 RegisterRecv 에서 SetBuffer를 해준다. 그 이유는 Start 부분에서 SetBuffer를 해주게 되면, OnSendCompleted에서 실행 되고 있는 RegisterRecv 부분에서 Read하고, Write하는 부분을 다시 재설정 해주지 못하기 때문이다.