Overlapped I/O 모델

Jaemyeong Lee·2025년 1월 28일

게임 서버1

목록 보기
136/220

Overlapped의 본질: 요청과 완료를 분리한다

핵심 사고 전환

  • recv/send는 "지금 실행해서 지금 결과 확인"에 가깝습니다.
  • WSARecv/WSASend(Overlapped)는 "지금 요청 등록, 완료는 나중에 통지"입니다.
  • 즉, 호출 스레드가 오래 기다리지 않고 다음 일을 진행할 수 있습니다.

Reactor vs Proactor

관점Select/WSAEventSelectOverlapped
흐름준비됨 감지 -> recv 호출WSARecv 먼저 등록 -> 완료 통지
패턴ReactorProactor
핵심 질문"지금 읽을 수 있나?""등록한 I/O가 끝났나?"

실무 핵심 한 줄

  • Overlapped 서버는 "완료 이벤트 처리 + 다음 I/O 재등록" 루프입니다.

기본 호출 패턴과 반환값 해석

최소 요청 코드

DWORD flags = 0;
DWORD bytes = 0;
int ret = WSARecv(sock, &wsaBuf, 1, &bytes, &flags, &ov, nullptr);

반환값 해석 규칙

경우의미처리
ret == 0즉시 완료bytes 즉시 처리
ret == SOCKET_ERROR + WSA_IO_PENDING정상(비동기 진행 중)완료 통지를 기다림
그 외 에러실제 실패로그 + 연결 종료/복구

자주 하는 실수

  • WSA_IO_PENDING을 실패로 처리하면 정상 요청을 끊어버리게 됩니다.

완료 통지 방식 3가지

방법 비교

방식장점한계/주의
이벤트(hEvent)동작이 직관적, 학습용 좋음이벤트/핸들 관리 비용, 대규모 비효율
콜백(Completion Routine)코드 흐름을 콜백으로 구성 가능Alertable wait(SleepEx) 의존, 디버깅 난이도
IOCP고성능, 대규모 확장성초기 설계 난이도 높음

이벤트 방식 예시

WSAEVENT ev = WSACreateEvent();
ov.hEvent = ev;

int r = WSARecv(sock, &buf, 1, &bytes, &flags, &ov, nullptr);
if (r == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
    // 실제 오류
}

WSAWaitForMultipleEvents(1, &ev, TRUE, WSA_INFINITE, FALSE);
WSAGetOverlappedResult(sock, &ov, &bytes, FALSE, &flags);

콜백 방식 핵심

  • Completion Routine은 호출 스레드가 Alertable wait에 들어가야 실행됩니다.
  • 실무 서버에서는 제어 복잡도 때문에 이벤트/IOCP를 더 많이 사용합니다.

버퍼와 OVERLAPPED 수명 규칙 (가장 중요)

절대 규칙

  • I/O 완료 전까지 WSABUF의 메모리와 OVERLAPPED는 살아 있어야 합니다.
  • 스택 버퍼/스택 OVERLAPPED를 등록 후 함수 종료하면 댕글링으로 크래시가 납니다.

동시 요청 규칙

  • Outstanding I/O 하나당 OVERLAPPED 하나가 필요합니다.
  • 같은 OVERLAPPED를 동시에 두 요청에 재사용하면 결과가 섞일 수 있습니다.

OverlappedEx 패턴

struct OverlappedEx {
    OVERLAPPED ov{};
    WSABUF     wsaBuf{};
    char       buffer[8192];
    int        ioType = 0;   // RECV / SEND
    void*      owner  = nullptr; // Session*
};
  • I/O 컨텍스트 구조체에 버퍼와 메타데이터를 함께 두면 수명 관리가 쉬워집니다.
  • 이 패턴은 Part 18의 IOCP에서도 그대로 이어집니다.

완료 처리 루프에서 꼭 지킬 것

수신 완료 처리 기본

  • 완료 바이트가 0이면 TCP graceful close로 보고 정리합니다.
  • > 0이면 패킷 파싱 후 다음 WSARecv를 재등록합니다.

송신 완료 처리 기본

  • 한 번의 완료로 전체 송신이 끝난다고 가정하지 마세요.
  • 남은 바이트가 있으면 다음 WSASend를 이어서 등록해야 안전합니다.

종료/취소 시나리오

  • 소켓 종료 중에는 대기 중 I/O가 취소되어 완료가 에러로 도착할 수 있습니다.
  • 종료 플래그를 두고 "늦게 도착한 완료"를 안전하게 무시/정리하는 정책이 필요합니다.

IOCP로 넘어가는 전환 기준

Overlapped만으로도 중요한 학습

  • "요청 등록 -> 나중 완료 처리 -> 재등록" 구조를 익히면 IOCP 이해가 쉬워집니다.

전환이 필요한 신호

  • 연결 수가 커지며 이벤트/핸들 관리가 부담이 될 때
  • 완료 처리를 여러 워커에 분산해야 할 때
  • 락 경쟁보다 완료 큐 기반 분배가 더 유리해질 때

결론

  • Overlapped는 종착점이 아니라 IOCP로 가는 핵심 중간 단계입니다.

강의 시 유의사항

강조 포인트

  • WSA_IO_PENDING은 에러가 아니라 정상 진행 신호입니다.
  • 수명 관리(버퍼/OVERLAPPED)는 성능보다 먼저 지켜야 하는 정합성 규칙입니다.
  • 완료 처리 후 재등록을 빼먹으면 수신이 멈춥니다.

자주 하는 오해

오해바로잡기
Overlapped면 자동으로 고성능 서버 완성완료 처리 설계/재등록/수명 관리가 핵심
WSA_IO_PENDING은 실패다비동기 요청이 정상 등록된 상태
OVERLAPPED 하나를 계속 재사용해도 된다Outstanding I/O마다 별도 컨텍스트 필요

체크 질문 (스스로 답해보기)

  • WSARecv 호출 직후 어떤 경우가 정상 경로이고 어떤 경우가 실제 에러인가?
  • OVERLAPPED와 버퍼를 스택에 두면 위험한가?
  • 수신 완료 후 다음 WSARecv를 재등록하지 않으면 어떤 현상이 생기는가?

profile
李家네_공부방

0개의 댓글