본문 바로가기

공부/tcp/ip 프로그래밍

22장 Overlapped IO 모델

반응형

 overlapped_io_모델.pptx

 

Overlapped IO 모델

 

Overlapped IO의 주안점
비동기 IO(nonblocking 모드 입출력함수) + 입출력 완료결과 확인

 

Overlapped IO에서 입출력의 완료 및 결과를 확인하는 2가지 방법

1. WSASend, WSARecv 함수의 여섯 번째 매개변수, Event 오브젝트 기반

    1) IO가 완료되면 WSAOVERLAPPED 구조체 변수가 참조하는 Event 오브젝트가 signaled 상태가 됨

        WSASend() 이용시

           1> 바로 전송이 완료되면 밑의 과정이 필요없음

           2> 바로 전송이 되지 못하고 시간이 걸릴 경우

                WSASend()의 반환 값 = SOCKET_ERROR, WSAGetLastError()의 반환 값 = WSA_IO_PENDING일때

                는 event오브젝트가 signaled 상태가 될 때까지 기다림

                (이를 위해 WSAWaitForMultipleEvents함수 이용)

    2) IO의 완료 및 결과를 확인하려면 WSAGetOverlappedResult 함수를 사용

 

2. WSASend, WSARecv 함수의 일곱 번째 매개변수, Completion Routine 기반

IO를 요청한 쓰레드가 ALERTABLE WAIT 상태에 놓여있을 때만 Completion Routine을 호출

 1) IO를 진행시킨 다음에 급한 다른 볼일들을 처리함

 2) IO가 완료되었는지 확인하고 싶을 때 alertable wait 상태를 만드는 함수들 중 하나를 호출

 3) 운영체제는 쓰레드가 alertable wait 상태에 진입한 것을 인식

 4) 완료된 IO가 있다면 이에 해당하는 Completion Routine을 호출

 5) Completion Routine이 실행되면 alertable wait 상태를 만드는 함수들은 모두

     WAIT_IO_COMPLETION을 반환하면서 함수를  빠져 나옴

6) 그 다음부터 실행을 이어감

 

alertable wait 상태를 만드는 함수

WaitForSingleObjectEx()

WaitForMultipleObjectsEx()

WSAWaitForMultipleEvents()

SleepEx()

 

Overlapped IO 모델 코딩 순서

1. Event 오브젝트 사용하기(함수 순서)

 

2. Completion Routine 사용하기(함수 순서)

 

Overlapped IO 소켓 생성함수

#include <winsock2.h>

 

SOCKET WSASocket(

int af, int type, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags);

성공 시 소켓의 핸들, 실패 시 INVALID_SOCKET 반환

 

af : 프로토콜 체계 정보 전달

type : 소켓의 데이터 전송방식에 대한 정보 전달

protocol : 두 소켓 사이에 사용되는 프로토콜 정보 전달

lpProtocolInfo : 생성되는 소켓의 특성 정보를 담고 있는 WSAPROTOCOL_INFO 구조체 변수의

                      주소 값 전달, 필요없는 경우 NULL 전달

g : 함수의 확장을 위해서 예약되어 있는 배개변수, 따라서 0 전달

dwFlags : 소켓의 속성정보 전달

 

Overlapped IO가 가능한 넌-블로킹 모드의 소켓 생성

WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

 

Overlapped IO에 사용할 수 있는 데이터 출력함수

#include <winsock2.h>

 

int WSASend(

SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,

LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

성공 시 0, 실패 시 SOCKET_ERROR 반환

 

s : 소켓의 핸들 전달, Overlapped IO 속성이 부여된 소켓의 핸들 전달 시 Overlapped IO 모델로 출력 진행

lpBuffers : 전송할 데이터 정보를 지니는 WSABUF 구조체 변수들로 이뤄진 배열의 주소 값 전달

dwBufferCount : 두 번째 인자로 전달된 배열의 길이정보 전달

lpNumberOfBytesSent : 전송된 바이트 수가 저장될 변수의 주소 값 전달

dwFlags : 함수의 데이터 전송특성을 변경하는 경우에 사용, 예로 MSG_OOB를 전달하면 OOB모드 데이터 전송

lpOverlapped : WSAOVERLAPPED 구조체 변수의 주소 값 전달, Event 오브젝트를 사용해서 데이터 전송의

                     완료를 확인하는 경우에 사용되는 매개변수

lpCompletionRoutine : Completion Routine이라는 함수의 주소 값 전달, 이를 통해서도 데이터 전송의 완료를 확인

 

typedef struct __WSABUF

{

u_long len;    //전송할 데이터의 크기

char FAR* buf; //버퍼의 주소 값

} WSABUF, *LPWSABUF;

 

typedef struct _WSAOVERLAPPED

{

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

WSAEVENT hEvent;

} WSAOVERLAPPED, *LPWSAOVERLAPPED;

 

사용 예 :

WSASend(hSocket, &dataBuf, 1, &recvBytes, 0, &overlapped, NULL);

 

* 주의점 :

1. Overlapped IO를 진행하려면 WSASend 함수의 매개변수 lpOverlapped에는 항상 NULL이 아닌, 유효한 구조체 변수의 주소 값을 전달해야 함, NULL이면 소켓은 블로킹 모드로 동작

2. WSASend 함수호출을 통해서 동시에 둘 이상의 영역으로 데이터를 전송하는 경우에는 여섯 번째 인자로 전달되는 WSAOVERLAPPED 구조체 변수를 각각 별도로 구성해야 함

3. WSASend 함수라고 해서 무조건 함수의 반환과 데이터의 전송완료 시간이 불일치 하는 것은 아님.

출력버퍼가 비어있고, 전송하는 데이터의 크기가 크지 않다면, 함수호출과 도시에 데이터의 전송이 완료 될 수 있음.

이 경우, WSASend 함수가 0을 반환하고, 매개변수 lpNumberOfBytesSent로 전달된 주소의 변수에는 실제 전송된 데이터의 크기정보가 저장

4. 호출된 WSASend 함수가 반환을 한 다음에도 계속해서 데이터의 전송이 이뤄지는 상황이라면 WSASend함수는 SOCKET_ERROR를 반환하고, WSAGetLastError함수호출을 통해서 확인 가능한 오류코드

로는 WSA_IO_PENDING이 등록

 

IO의 완료를 되어 실제로 전송된 데이터의 크기를 확인하는 함수

#include <winsock2.h>

 

BOOL WSAGetOverlappedResult(

SOCKET s, LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer, BOOL fWait, LPDWORD lpdwFlags);

성공 시 TRUE, 실패 시 FALSE 반환

s : Overlapped IO가 진행된 소켓의 핸들

lpOverlapped : Overlapped IO 진행 시 전달한 WSAOVERLAPPED 구조체 변수의 주소 값 전달

lpcbTransfer : 실제 송수신된 바이트 크기를 저장할 변수의 주소 값 전달

fWait : 여전히 IO가 진행중인 상황의 경우, TRUE 전달 시 IO가 완료될 때까지 대기를 하게 되고, FALSE전달 시 FALSE를 반환하면서 함수를 빠져 나온다

lpdwFlags : WSARecv함수가 호출된 경우, 부수적인 정보(수신된 메시지가 OOB 메시지인지 여부)를 얻기 위해 사용. 불필요하면 NULL을 전달

 

Overlapped IO에 사용할 수 있는 데이터 입력함수

#include <winsock2.h>

 

int WSARecv(

SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,

LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped,

LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

성공 시 0, 실패 시 SOCKET_ERROR 반환

 

s : Overlapped IO 속성이 부여된 소켓의 핸들 전달

lpBuffers : 수신된 데이터 정보가 저장될 버퍼의 정보를 지니는 WSABUF 구조체 배열의 주소 값 전달

dwBufferCount : 두 번째 인자로 전달된 배열의 길이정보 전달

lpNumberOfBytesRecvd : 수신된 데이터의 크기정보가 저장될 변수의 주소 값 전달

lpFlags : 전송특성과 관련된 정보를 지정하거나 수신하는 경우에 사용

lpOverlapped : WSAOVERLAPPED 구조체 변수의 주소 값 전달

lpCompletionRoutine : Completion Routine이라는 함수의 주소 값 전달

 

소켓 관련함수가 호출된 이후에 발생하는 오류의 원인정보 확인함수

#include <winsock2.h>

 

int WSAGetLastError(void);

오류상황에 대한 상태 값(오류의 원인을 알리는 값) 반환

 

IO의 완료를 확인하는 함수

void CALLBACK CompletionROUTINE(

DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);

 

dwError : 오류정보가 전달됨(정상종료 시 0 전달)

cbTransferred : 완료된 입출력 데이터의 크기정보가 전달됨

lpOverlapped : WSASend, WSARecv 함수의 매개변수 lpOverlapped로 전달된 값

dwFlags : 입출력 함수호출 시 전달된 특성정보 또는 0이 전달됨

키워드 CALLBACK은 쓰레드의 main 함수에 선언되는 키워드인 WINAPI와 마찬가지로 함수의 호출규약을 선언한 것

 

반응형