지금까지 만들어놓은 RecvBuffer에서 문제점은 TCP방식으로 받고있다보니 패킷으로 데이터를 받게되었을때 일부가 손실된채로 올수가있다. 그것에 대한 처리가 전혀 없기때문에 나중에 패킷으로 데이터를 받을때를 대비해서 시스템을 구축 해놓고자한다.
recvArgs.SetBuffer(new byte[1024],0,1024);
기존이 코드는 매번 새로운byte배열을 불러주었다. 당연히 비효율적이다.
만들고자 하는것을 설명하자면
1.일종의 2개의 포인터를 두는것이다.
_readPosition : 읽기를 시도했을때 _readPosition과 writePosition사이에 있는 값들을 읽어줌 즉, 배열에 유효한 데이터의 시작점
_writePosition :배열에서 유효한 데이터의 끝점이라고 보면된다.
2.위의 2개를 가지고서
DataSize : 유효한 데이터 크기
FreeSize : Receive할 수있는 데이터 크기
ReadSegment: 버퍼에서 유효한 데이터가 들어있는 부분배열
WriteSegment : 버퍼에서 추가로 받을 수 있는 부분배열
같은 변수를 만든다.
3.함수 3개도 만들어주는데Clear(): 버퍼의 크기는 정해져있기때문에(여기서는 1024바이트로 설정) _readPosition 과 _writePosition의 위치를 다시 초기화 해주지않으면 어느 시점부터는 버퍼의 크기를 넘어간다.
이때 상황에 맞춰서 초기화를 해줘야하는데상황 1 : _readPosition == _writePosition인 경우 그 사이에 데이터가 없다는 뜻이므로 이 둘을 0으로 만든다.
상황 2: _readPosition < _writePosition 인 경우 사이에 데이터가 있다는 뜻이므로 _readPosition를 0으로 돌려주되 _writePosition 사이에 있는 값까지 함께 가지고 가야한다.
OnRead():제대로 다 도착해서 성공적으로 처리했는지 bool 값을 반환함
3바이트 2개 총 6바이트를 보냈을때 버퍼에 4바이트만와 있다면 앞의 3바이트는 작업하고 뒤의 1바이트는 나머지 2바이트가 올때 까지 기다려야한다. 이때 앞의 3바이트가 도착했는지를 확인하는 용도라고 생각하면된다.
OnWrite():현재 보낼 수있는 여유 공간이있는지 지속적으로 Clear()를 할것이기때문에 이게 false로 반환된다면 어디선가 문제가 발생했을것이다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ServerCore
{
public class ReceiveBuiffer
{
ArraySegment<byte> _buffer;
int _readPosition;
int _writePosition;
public ReceiveBuiffer(int bufferSize)
{
_buffer = new ArraySegment<byte>(new byte[bufferSize], 0 ,bufferSize);
}
public int DataSize { get { return _writePosition - _readPosition; } }
public int FreeSize { get { return _buffer.Count - _writePosition; } }
public ArraySegment<byte> ReadSegment //유효데이터 범위의 부분배열
{
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _readPosition, DataSize); }
}
public ArraySegment<byte> WriteSegment //받을수있는 데이터 범위의 부분배열
{
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _writePosition, FreeSize); }
}
public void Clear()
{
int dataSize = DataSize;
if(dataSize == 0) //커서가 같은곳에있으니 존재하는 데이터가 없음
{
_readPosition = _writePosition = 0;
}
else
{
//Array에서 read위치를 dataSize만큼을 복사해서 Array의 시작위치에 올려놓음
Array.Copy(_buffer.Array, _buffer.Offset + _readPosition, _buffer.Array, _buffer.Offset,dataSize);
_readPosition = 0;
_writePosition = dataSize;
}
}
public bool OnRead(int numOfBytes) //제대로 다 도착해서 성공적으로 처리했는지
{
if(numOfBytes > DataSize)
return false;
_readPosition += numOfBytes;
return true;
}
public bool OnWrite(int numOfBytes)
{
if (numOfBytes > FreeSize)
return false;
_writePosition += numOfBytes;
return true;
}
}
}
'서버 공부' 카테고리의 다른 글
| [서버 공부]16.PacketSession (0) | 2025.01.16 |
|---|---|
| [서버 공부]15.SendBuffer (0) | 2025.01.15 |
| [서버 공부]12 Session 1,2 (0) | 2025.01.12 |
| [서버 공부]11. Listener (0) | 2025.01.12 |
| [서버 공부]10. 소켓 프로그래밍 (0) | 2025.01.10 |