2016년 6월 9일 목요일

뇌자극 TCP_IP 프로그래밍 18강 요약

18강 윈도우 고급 네트워크 프로그래밍

1. 윈속 확장 함수

모든 윈속 확장 함수는 WSA로 시작하며 기본적인 소켓 함수들에 대한 확장 함수도 제공한다

socket 함수에 대응되는 윈속 확장 함수인 WSASocket 함수다.

SOCKET WSASocket (
  __in intaf,
  __in int type,
  __in int protocol,
  __in LPWSAPROTOCOL_INFO lpProtocolInfo,
  __in GROUP g,
  __in DWORDdwFlags
);

2. WSAEventSelect 네트워크 프로그램 개발

이벤트 객체와 select 함수를 이용한 비동기 입출력 모델이다.

이벤트 객채 생성

WSAECENT WSACreateEvent(void)l

이벤트 객체를 소켓과 묶어주기

이벤트 객체가 작동하려면 이벤트를 기다릴 소켓과 이벤트 종류를 지정해 줘야 한다.

int WSAEventSelect(
  __in SOCKET s,
  __in WSAEVENT hEventObject,
  __in long lNetworkEvents
);

s : 이벤트 객체와 묶어줄 소켓 지정번호
hEventObject : 소켓 s와 묶어줄 이벤트 객체
lNetworkEvents : 이벤트 객체를 신호 상태로 만들기 위해서 기다릴 이벤트 목록

이벤트 값

FD_READ : 입력 이벤트
FD_WRITE : 출력 이벤트
FD_OOB : 긴급 데이터(OOB) 이벤트
FD_ACCEPT : 클라이언트 연결 요청 이벤트
FD_CONNECT : 연결 완료 이벤트
FD_CLOSE : 연결 종료 이벤트

비트 연산으로 하나의 소켓에 여러 이벤트를 발생하도록 지정할 수 있다.
WSAEventSelect(s, hEventObject, FD_READ | FD_WRITE);

이벤트 기다리기

DWORD WSAWaitForMultipleEvents(
  __in DWORD cEvents,
  __in const WSAEVENT *lphEvents,
  __in BOOL fWaitAll,
  __in DWORD dwTimeout,
  __in BOOL fAlertable
);

cEvents : lphEvent의 배열의 크기로 이벤트를 기다릴 이벤트 객체 핸들의 개수다.
lphEvents : 이벤트 객체 핸들 배열을 가리키는 포인터다.
fWaitAll : 기다림의 방식을 지정한다.
   true 라면 모든 이벤트 객체가 신호 상태가 되어야 반환한다.
   false라면 핸들 중 하나라도 신호 상태가 되면 반환한다.
   일반적으로 false를 사용한다.
dwTimeout : 신호 상태를 기다리는 제한 시간이다. (WSA_INFINITE를 설정하면 무한정 기다린다.)
fAlertable : true로 설정하면 이벤트 객체를 가지고 작업할 스레드가 반응할 수 있는 상태에 놓일 때까지 호출되지 않게 된다.

이벤트 종류 알아내기

int WSAEnumNetworkEvents(
  __in SOCKET s,
  __in WSAEVENT hEventObject,
  __out LPWSANETWORKEVENTS lpNetworkEvents
);

s : 이벤트가 발생한 소켓 지정번호
hEventObject : 이벤트 객체를 리셋하기 위해서 사용한다.
lpNetworkEvents : 이벤트의 종류 값을 가지고 있는  WSANETWORKEVENTS 구조체의 포인터다. 이 구조체는 다음과 같이 정의되어 있다.

typedef struct _WSANETWORKEVENTS {
  long lNetworkEvents;
  int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS , *LPWSANETWORKEVENTS;

lNetworkEvents : 이벤트의 종류를 확인할 수 있다.
iErrorCode : 에러 코드를 저장한다.

3. WSAAsyncEvent 네트워크 프로그램 개발

윈도우 메시지 형태로 네트워크 이벤트를 처리한다.

1) 소켓을 위한 윈도우와 처리할 네트워크 이벤트를 등록한다.
2) 소켓에 등록한 이벤트가 발생하면 관련 정보가 메시지 큐에 들어간다.
   이 정보에는 이벤트가 발생한 소켓 지정 번호가 포함된다.
3) 윈도우 프로시저가 호출되고, 이벤트 종류에 따라서 처리하면 된다.

윈도우 객체와 메시지 처리

윈도우 메시지를 사용하므로 반드시 윈도우 객체가 있어야 한다.

HWND CreateWindow(
  __in LPCTSTR lpClassName,
  __in LPCTSTR lpWindowName,
  __in DWORD dwStyle,
  __in int x,
  __in int y,
  __in int nWidth,
  __in int nHeight,
  __in HWND hWndParent,
  __in HMENU hMenu,
  __in HINSTANCE hInstance,
  __in LPVOID lpParam
);

lpClassName : 등록된 윈도우 클래스 이름
lpWindowName : 윈도우 타이틀에 표시될 이름
dwStyle : 윈도우 스타일
x : 수평 좌표
y : 수직 좌표
nWidth : 윈도우 넓이
nHeight : 윈도우 높이
hWndParent : 윈도우를 소유할 부모 윈도우의 핸들러
hMenu : 윈도우에서 사용할 메뉴의 핸들러
hInstance : 윈도우와 연결될 인스턴스 핸들러
lpParam : 메시지 정보

소켓 메시지를 처리할 윈도우 객체 지정

int WSAAsyncSelect(
  __in SOCKET s,
  __in HWND hWnd,
  __in unsigned int wMsg,
  __in long lEvent
);

s : 이벤트를 기다릴 소켓을 가리키는 소켓 지정번호
hWnd : 이벤트가 발생했을 때 메시지를 처리할 윈도우 객체 핸들러
wMsg : 발생한 소켓 이벤트를 가리키는 번호
lEvent :  기다릴 소켓 이벤트의 종류

이벤트 종류

FD_READ : 입력 이벤트
FD_WRITE : 출력 이벤트
FD_OOB : 긴급 데이터(OOB) 이벤트
FD_ACCEPT : 클라이언트 연결 요청 이벤트
FD_CONNECT : 연결 완료 이벤트
FD_CLOSE : 연결 종료 이벤트

4. 중첩 입출력 모델

윈도우는 멀티 태스킹을 지원하므로 파일 입출력도 동시에 다룰 수 있다.
동시에 여러 개를 입력하면 데이터가 중첩되는 영역이 생긴다.
중첩 입출력 모델은 데이터가 중첩되며 동시에 처리할 수 있다.

중첩 소켓 만들기

SOCKET WSASocket (
  __in int af,
  __in int type,
  __in int protocol,
  __in LPWSAPROTOCOL_INFO lpProtocolInfo,
  __in GROUP g,
  __in DWORD dwFlags
);

lpProtocolInfo : 소켓의 특성을 정의한 LPWSAPROTOCOL_INFO 구조체의 포인터
g : 소켓 그룹의 식별자
dwFlags : 소켓 속성을 지정

중첩 소켓을 이용한 데이터 처리

int WSAARecv (
  __in SOCKET s
  __inout LPWSABUF lpBuffers,
  __in DWORD dwBufferCount,
  __out LPDWORD lpNumberOfBytesRecvd,
  __inout LPDWORD lpFlags,
  __in LPWSAOVERLAPPED lpOverlapped,
  __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

s : 데이터를 쓸 소켓 지정 번호
lpBuffers : 전송할 데이터의 정보를 담고 있는 WSABUF 구조체의 배열을 가리키는 포인터
dwBufferCount : lpUbffers의 배열의 크기다.
lpFlags : recv 함수의 flags와 같은 일을 한다.

소스 코드 받기

댓글 없음:

댓글 쓰기