Published on

비동기(Asynchronous) Notification IO 모델의 이해

Authors
  • avatar
    Name
    JaeHyeok CHOI
    Twitter
    none

비동기(Asynchronous) Notification IO

동기와 비동기에 대한 이해

  • Synchronous

윈도우 기반 예제에서 send & recv 함수를 통해서 동기화된 입출력을 진행했었다. send 함수가 호출되면 데이터의 전송이 완료된 후에 반환이 이뤄지고(출력 버퍼로 데이터가 완전히 전송된 후) recv 함수가 호출되면 원하는 만큼 데이터를 읽어 들인 후에 반환이 이뤄지기 때문에 동기화된 입출력을 진행한 것이다.

  • Asynchronous

이와 반대로, 비동기 입출력이란 입출력 함수의 반환시점과 데이터의 송수신의 완료 시점이 일치하지 않는 경우이다.

비동기 Notification 입출력 모델의 이해

  • Notification IO
    • 입력 버퍼에 데이터가 수신되어 데이터의 수신이 필요하거나, 출력 버퍼가 비어서 데이터의 전송이 가능한 상황의 알림
    • 대표적인 방법이 select 방식이다.
  • select 함수
    • IO가 필요한, 가능한 상황이 되는 시점이 select 함수가 반환하는 시점과 일치한다.
  • WSAEventSelect 함수
    • IO의 상태에 상관없이 반환이 이루어지는 방식

비동기(Asynchronous) Notification IO 모델의 구현

  • WSAEventSelect 함수
  • WSAAsyncSelect 함수: 발생한 이벤트를 수신할 윈도우의 핸들을 지정해야함.

IO의 상태 변화

  • 소켓의 상태변화 - 소켓에 대한 IO의 상태 변화
  • 소켓의 이벤트 발생 - 소켓에 대한 IO 관련 이벤트의 발생

WSAEventSelect 함수

임의의 소켓을 대상으로 이벤트 발생 여부의 관찰을 명령한다.

#include <winsock2.h>

int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, long lNetworkEvents);
  • s : 관찰 대상인 소켓의 핸들 전달
  • hEventObject : 이벤트 발생 유무의 확인을 위한 Event 오브젝트의 핸들
  • lNetworkEvents : 감시하고자 하는 이벤트의 유형 정보 전달

WSAEventSelect 함수는 매개변수 s에 전달된 핸들의 소켓에서 lNetworkEvents에 전달된 이벤트 중 하나가 발생시, hEventObject에 전달된 핸들의 커널 오브젝트를 signaled 상태로 바꾸는 함수이다. (Event 오브젝트와 소켓을 연결하는 함수)

  • lNetworkEvents 의 유형 정보
    • FD_READ : 수신할 데이터가 존재?
    • FD_WRITE : 블로킹 없이 데이터 전송이 가능한가?
    • FD_OOB : Out Of Band 데이터가 수신되었는가?
    • FD_ACCEPT : 연결 요청이 있었는가?
    • FD_CLOSE : 연결의 종료가 요청되었는가?

WSACreateEvent 함수

  • CreateEvent 함수
    • Event 오브젝트를 생성
      • auto-reset 모드
      • manual-reset 모드
  • WSACreateEvent 함수
    • manual-reset , non-signaled 상태
 #include <winsock2.h>

WSAEvent WSACreateEvent(void);

WSAWaitForMultipleEvents 함수

#include <winsock2.h>

DWORD WSAWaitForMultipleEvents(DWORD cEvents, const WSAEVENT* lphEvents,
 BOOL fwaitAll, DWORD dwTimeout, BOOL fAlertable);
  • cEvents :
    • signaled 상태로의 전이 여부를 활인할 Event 오브젝트의 개수
  • lphEvents :
    • Event 오브젝트의 핸들을 저장하고 있는 배열의 주소
  • fwaitAll :
    • TRUE - Event오브젝트가 signaled 상태 일 때 반환, FASLE - 전달시 하나만 signaled 상태가 되어도 반환
  • dwTimeout :
    • 1/1000 초 단위로 타임아웃 지정, WSA_INFINITE 전달 시 signaled 상태까지 반환하지 않음
  • fAlertable :
    • 반환된 정수 값에서 상수 값 WSA_WAIT_EVENT_0 를 빼면, 두 번째 매개변수로 전달된 배열을 기준으로, signaled 상태가 된 Event 오브젝트의 핸들이 저장된 인덱스가 계산된다. 만약, 둘 이상의 Event 오브젝트가 signaled 상태로 전이 되었다면, 그 중 작은 값이 계산된다. 그리고 타임아웃이 발생하면 WAIT_TIMEOUT이 반환된다.

최대 핸들의 수는 64개로 제한되어 있어서, 그 이상의 핸들을 관찰해야 한다면 쓰레드의 생성을 통한 확장을 시도하거나 핸들을 저장하고 있는 배열을 구분해서 위 함수를 두 번 이상 호출하는 방법을 고려한다.