| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- 이분 탐색
- ccw 알고리즘
- Binary Lifting
- SCC
- JavaScript
- 비트필드를 이용한 dp
- 최소 공통 조상
- Strongly Connected Component
- 2-SAT
- 강한 연결 요소
- 비트마스킹
- Lock-free Stack
- 그래프 탐색
- Overlapped Model
- map
- DP
- Delete
- 트라이
- 벨만-포드
- HTTP
- select 모델
- Spin Lock
- Prisma
- trie
- Github
- 자바스크립트
- reference counting
- Behavior Design Pattern
- PROJECT
- 게임 서버 아키텍처
Archives
- Today
- Total
dh_0e
[C++/Game Server] SendBuffer (+GameSession) 본문
SendBuffer
- 목적
- 메모리 파편화 해결: 작은 패킷을 보낼 때마다 메모리를 할당/해제하면 시스템 성능이 저하됨
- 할당 비용 감소: 고성능 서버에서는 매 초당 수만 개의 패킷이 오가는데, 그때마다 커널에 메모리를 요청하는 것은 비효율적임
- 수명 보장: 비동기 I/O(IOCP) 특성상 WSASend가 완료될 때까지 버퍼가 살아있음을 보장해야 함
- 전송 흐름
- Send(): 버퍼를 당장 보내는 것이 아니라 _sendQueue에 일단 담고 RegisterSend가 이미 돌아가고 있다면 종료
- RegisterSend(): RegisterSend가 준비(_sendRegistered==false)됐다면 큐에 쌓인 모든 버퍼를 _sendEvent의 sendBuffers 벡터에 옮김
- 이때, Scatter-Gather를 위해 wsaBufs 배열을 준비해서 버퍼 데이터들의 정보를 담아줌
- Scatter-Gather I/O: 한 번에 묶어 보내기
- 여러 개로 흩어져 있는 메모리 블록(SendBuffer)을 한 번의 시스템 콜(WSASend)로 모아서 보내는 기법
- 패킷이 생길 때마다 전송 함수를 호출하는 대신, 큐에 쌓인 것들을 한 번에 처리하므로 커널 모드 전환 비용을 줄여줌
- WSASend()로 버퍼 데이터 전송 요청
- Dispatch(): 전송이 완료되면 ProcessSend에서 RELEASE_REF 후에 OnSend() 호출
- ProcessSend(): _sendQueue가 그새 찼다면 RegisterSend() 호출 / 아니면 _sendRegistered false로 변경해서 다음 Send가 RegisterSend를 호출할 수 있게 해 줌
- Buffer Data Structure: 모두 SendBufferRef로 관리해서 이동 연산 비용도 아끼고, owner 처리로 Ref Count도 적용
- Queue<SendBufferRef> Session::_sendQueue: 보내려고 줄 서 있는 버퍼 데이터 큐
- Vector<SendBufferRef> SendEvent::sendBuffers: 시스템 콜로 보내고 있는 중이라서, 절대 메모리에서 사라지면 안 되는 데이터
- 참조 횟수 유지, 완료 시점까지 보존 역할을 하며, ProcessSend에서 마지막에 clear 되며 SendBuffer 소멸자 발동
- Vector<WSABUF> wsaBufs: OS에게 데이터 버퍼의 길이(len)와 포인터(*buf)를 알려주기 위한 주소록
SendBuffer.h
#pragma once
/*------------------
SendBuffer
-------------------*/
class SendBuffer : enable_shared_from_this<SendBuffer> {
public:
SendBuffer(int32 bufferSize);
~SendBuffer();
BYTE* Buffer() { return _buffer.data(); }
int32 WriteSize() { return _writeSize; }
int32 Capacity() { return static_cast<int32>(_buffer.size()); }
void CopyData(void* data, int32 len);
private:
Vector<BYTE> _buffer;
int32 _writeSize;
};
SendBuffer.cpp
#include "pch.h"
#include "SendBuffer.h"
/*------------------
SendBuffer
-------------------*/
SendBuffer::SendBuffer(int32 bufferSize) {
_buffer.resize(bufferSize);
}
SendBuffer::~SendBuffer() {}
void SendBuffer::CopyData(void* data, int32 len) {
ASSERT_CRASH(Capacity() >= len);
::memcpy(_buffer.data(), data, len);
_writeSize = len;
}
CorePch.h / IocpEvent.h / Session.h / Session.cpp / Types.h 수정
SendBuffer · znfnfns0365/CPP_Server_Practice@978def9
- if (SOCKET_ERROR == ::WSASend(_socket, &wsaBuf, 1, OUT & numOfBytes, 0, sendEvent, nullptr)) {
github.com
- CorePch.h: SendBuffer 헤더 추가
- IocpEvent.h: WSASend 완료 시점까지 데이터를 보존하는 vector인 sendBuffers 선언
- Session.h: _sendQueue, _sendRegistered, _sendEvent 선언
- Session.cpp
- Send(): _sendQueue에 버퍼 삽입 로직, _sendRegistered를 확인하여 RegisterSend() 호출
- RegisterSend(): _sendQueue의 버퍼를 sendBuffers로 옮겨주고 wsaBufs로 주소록 저장 및 WSASend 호출
- ProcessSend(): RELEASE_REF, 다음 RegisterSend를 바로 호출할지 호출 대기시킬지 결정
- Types.h: SendBufferRef 정의
GameSession, GameSessionManager 생성 및 initialize
GameSession, GameSessionManager Class 생성 및 initialize · znfnfns0365/CPP_Server_Practice@66e221c
+ MakeShared<ClientService>(NetAddress(L"127.0.0.1", 7777), MakeShared<IocpCore>(), MakeShared<ServerSession>, 5);
github.com
- GameSession: 각 클라이언트마다 하나의 GameSession 객체 할당
- OnRecv(), OnSend()로 데이터 송수신 로직 관리
- OnConnected(), OnDisconnected()로 연결/해제 로직 관리
- GameSessionManager: 서버에 연결된 모든 GameSessionRef를 보관하는 컨테이너 (보통 Set이나 Map을 사용)
- Add(), Remove()로 세션 추가/ 제거
- Broadcast()로 모든 유저에게 패킷 전송
- GameSessionRef(shared_ptr)로 관리되므로, 매니저가 들고 있는 동안에는 세션 객체가 메모리에서 사라지지 않도록 보장함


- 두 상황에서 원활한 통신과 클라이언트/서버 종료 시 GameSession/ServerSession 소멸자가 잘 작동하는 것을 확인할 수 있음
'C++ > Game Server' 카테고리의 다른 글
| [C++/Game Server] RecvBuffer (0) | 2026.05.05 |
|---|---|
| [C++/Game Server] IOCP 기반 Session 및 비동기 연결 관리 (0) | 2026.04.30 |
| [C++/Game Server] IocpObject Ref Count, Service(Server/Client) (0) | 2026.04.24 |
| [C++/Game Server] IocpCore (0) | 2026.03.31 |
| [C++/Game Server] Socket Utils (WinSock Wrapper) (0) | 2026.03.29 |
