public abstract class Session
{
// ...
public void Start(Socket socket)
{
_socket = socket;
_recvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnRecvComplete);
// 현재 recv버퍼를 아래와 같이 쓰고 있는데 문제점은
_recvArgs.SetBuffer(new byte[1024], 0/*시작인덱스*/, 1024);
// ...
void OnRecvComplete(object sender, SocketAsyncEventArgs args)
{
if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success)
{
try
{
// TCP 특성상 모든 데이터가 다 도착하기전 OnRecv가 호출될 수 있다.
// 모든 데이터를 다 수신받은 후 OnRecv가 호출되게 만들어 보자
OnRecv(new ArraySegment<byte>(args.Buffer, args.Offset, args.BytesTransferred));
RegisterRecv();
}
// ...
개선해보자
// RecvBuffer.cs
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;
}
}
}