Server/C++

WSARecv에서 순환버퍼의 사용

Juzdalua 2024. 8. 16. 11:49

1차원 배열을 연속적으로 이어져있는 것처럼 사용하는 방식

데이터를 수신하면 한 번에 모든 데이터를 읽을 수 없고 계속해서 데이터가 수신될 때,

데이터 순서가 보장되지 않는 TCP의 단점을 보완하기 위한 방법.

 

readPos와 writePos가 같으면 현재 데이터가 없는 것이다.
=> 모든 인덱스를 초기 위치로 이동.

데이터를 읽는 도중 버퍼의 공간이 부족할 때
=> 데이터와 인덱스를 배열의 초기 위치 기준으로 복사한다.
1. 버퍼 생성
[][][][][] -> [rw][][][][]

2. 2byte 데이터 수신
[r][][w][][]

3. 2byte 데이터 수신
[r][][][][w]

4. 수신 처리 완료 => 인덱스 이동
[][][][][rw] -> [rw][][][][]

---------------------------------

1. 버퍼 생성
[][][][][] -> [rw][][][][]

2. 4byte 데이터 수신
[r][][][][w]

3. 3byte만 수신 완료 => 데이터 복사 및 인덱스 이동
[][][r][][w] -> [r][][w][][]

 

// 1. 버퍼 세팅
int32 BUFFER_SIZE = 0x10000;
int32 BUFFER_COUNT = 10;

int32 _capacity = 0;
int32 _bufferSize = 0;
int32 _readPos = 0;
int32 _writePos = 0;
Vector<BYTE> _recvBuffer;

_bufferSize = BUFFER_SIZE;
_capacity = _bufferSize * BUFFER_COUNT;
_recvBuffer.resize(_capacity);

// 2. recv
WSABUF wsaBuf;
wsaBuf.buf = reinterpret_cast<char*>(_recvBuffer[_writePos]);
wsaBuf.len = _capacity - _writePos;

DWORD numOfBytes = 0;
DWORD flags = 0;
WSARecv(SOCKET, &wsaBuf, 1, OUT & numOfBytes, OUT & flags, OVERLAPPED, nullptr);


// 3. index 확인
int32 dataSize = _writePos - _readPos;
int32 freeSize = _capacity - _writePos;

if (numOfBytes <= freeSize)
	_writePos += numOfBytes;

if (numOfBytes <= dataSize)
	_readPos += numOfBytes;

// 4. index 정리
if (dataSize == 0)
{
	_readPos = _writePos = 0;
}
else
{
	// 여유 공간이 버퍼 1개 크기 미만
	if (freeSize < _bufferSize)
	{
		memcpy(&_recvBuffer[0], &_recvBuffer[_readPos], dataSize);
		_readPos = 0;
		_writePos = dataSize;
	}
}

 

버퍼 공간이 부족해서 데이터와 인덱스를 배열의 초기위치로 복사하는 경우보다,

readPos와 writePos가 같아 인덱스만 배열의 초기 위치로 이동시키는 경우의 비용이 상대적으로 낮다.

따라서 버퍼의 크기를 상대적으로 크게 설정하면 유리하다.

 

코드)

https://github.com/Juzdalua/Study-Cpp-Server/blob/master/ServerCore/RecvBuffer.h

 

Study-Cpp-Server/ServerCore/RecvBuffer.h at master · Juzdalua/Study-Cpp-Server

Study C++ IOCP. Contribute to Juzdalua/Study-Cpp-Server development by creating an account on GitHub.

github.com

 

'Server > C++' 카테고리의 다른 글

문자집합과 인코딩  (0) 2024.08.19
WSASend에서 Scatter-Gather 기법 사용하기  (0) 2024.08.16
class 자신을 참조하는 shared_ptr  (0) 2024.08.13
IOCP Completion Port 모델  (0) 2024.08.13
Overlapped 모델  (0) 2024.08.13