ChattingServer
[ChattingServer] RecvPost ( WSARecv 걸기 )
program-yam
2025. 6. 2. 18:41
2025.06.01 - [ChattingServer] - [ChattingServer] RingBuffer ( 원형 큐 )
[ChattingServer] RingBuffer ( 원형 큐 )
서버에서 수신 버퍼로 사용하기 위해 RingBuffer를 구현했다. 🔁 링 버퍼( Ring Buffer )고정 크기의 원형 큐 형태의 자료구조로, FIFO( First-In-First-Out ) 방식으로 데이터를 저장한다. 📦 구조구성 요소
program-yam.tistory.com
앞서 포스팅한 RingBuffer( 원형 큐 )를 이용해 클라이언트로부터 데이터를 받는다.
원형큐이므로 연속으로 한번에 데이터를 넣을 수 있는 공간과 전체 남은 공간을 비교해서 링버퍼가 2개로 나뉘어있는지 확인해 WSABUF를 구성한다.
IOCount를 증가 시켜 지금 session이 사용중임을 기록하고 WSARecv를 건다.
void CoreNetwork::RecvPost(Session* recvSession, bool isAcceptRecvPost)
{
int recvBuffCount = 0;
WSABUF recvBuf[2];
// recvRingBuffer에 한번에 넣을 수 있는 크기를 읽는다.
int directEnqueueSize = recvSession->recvRingBuffer.GetDirectEnqueueSize();
// 남아 있는 recvRingBuffer의 크기를 읽는다.
int recvRingBuffFreeSize = recvSession->recvRingBuffer.GetFreeSize();
// 만약 남아 있는 recvRingBuffer의 크기가 한번에 넣을 수 있는 크기보다 크다면
// recvRingBuffer가 2개의 공간으로 나뉘어 있는 것을 확인할 수 있다.
if (recvRingBuffFreeSize > directEnqueueSize)
{
recvBuffCount = 2;
recvBuf[0].buf = recvSession->recvRingBuffer.GetRearBufferPtr();
recvBuf[0].len = directEnqueueSize;
recvBuf[1].buf = recvSession->recvRingBuffer.GetBufferPtr();
recvBuf[1].len = recvRingBuffFreeSize - directEnqueueSize;
}
else
{
recvBuffCount = 1;
recvBuf[0].buf = recvSession->recvRingBuffer.GetRearBufferPtr();
recvBuf[0].len = directEnqueueSize;
}
// WSARecv를 걸기 전에 한번 청소해준다.
memset(&recvSession->recvOverlapped, 0, sizeof(OVERLAPPED));
if (isAcceptRecvPost == false)
{
InterlockedIncrement64(&recvSession->IOBlock->IOCount);
}
DWORD flags = 0;
int WSARecvRetval = WSARecv(recvSession->clientSocket, recvBuf, recvBuffCount, NULL, &flags, (LPWSAOVERLAPPED)&recvSession->recvOverlapped, NULL);
if (WSARecvRetval == SOCKET_ERROR)
{
DWORD error = WSAGetLastError();
if (error != ERROR_IO_PENDING)
{
if (InterlockedDecrement64(&recvSession->IOBlock->IOCount) == 0)
{
ReleaseSession(recvSession);
}
}
}
}