AsyncSelect_

Download Report

Transcript AsyncSelect_

WSAAsync Select
김대열
Bit - Academy
Sunmoon University, Korea
1
목차
◆ WSAAsyncSelec 모델이란?
◆ WSAAsync Select 모델 – 장.단점
◆ WSAAsync Select 모델동작원리
◆ WSAAsyncSelect 모델을 이용한 소켓 입출력 절차
◆ WSAAsyncSelect() 함수
◆ 네트워크 이벤트
◆ 윈도우 프로시저
◆ WSAAsyncSelect() 사용시 유의할 점
2
WSAAsync Select 모델이란?
– WSAAsyncSelect() 함수가 핵심적인 역할을 함
– 윈도우 메시지 형태로 소켓과 관련된 네트워크 이벤트를 처리
 멀티스레드를 사용하지 않고도 여러 개의 소켓을 처리 가능
- 윈도우 메시지를 통하여 비동기적으로 소켓을 활용할 수 있음.
3
WSAAsync Select 모델 – 장.단점
● 장점
- 소켓 이벤트를 윈도우 메시지 형태로 처리하므로, GUI 애플리케이션과 잘 결합 할 수
있음.
● 단점
- 하나의 윈도우 프로시저에서 일반 윈도우 메시지와 소켓 메시지를 처리해야 하므로
성능저하의 요인이 됨.
- 윈도우가 없는 콘솔 프로그램등은 사용할 수 없음.
4
WSAAsync Select 모델동작원리
소켓 관련 메시지
메시지 큐
5
WSAAsyncSelect 모델을 이용한 소켓 입출력 절차
① WSAAsyncSelect() 함수를 이용하여 소켓을 위한 윈도우 메시지
와 처리할 네트워크 이벤트를 등록.
ex) 소켓을 통해 데이터를 보내거나 받을 수 있는 상황이 되면 특
정 윈도우 메시지로 알려달라는 내용을 등록.
② 등록한 네트워크 이벤트가 발생하면 윈도우 메시지가 발생하고
윈도우 프로시저가 호출.
③ 윈도우 프로시저에서는 받은 메시지 종류에 따라 적절한 소켓 함
수를 호출하여 처리.
6
WSAAsyncSelect() 함수
int WSAAsyncSelect (
SOCKET s,
HWND hWnd,
unsigned int wMsg,
long lEvent
);
처리하고자 하는 소켓
메시지를 받을 윈도우의 핸들
윈도우가 받을 메시지 (사용자 정의메시지)
처리할 네트워크 이벤트 종류 (비트 마스크 조합)
성공: 0, 실패: SOCKET_ERROR
· 사용자 정의 윈도우 메시지 사용 예
#define MWM_SOCKET (WM_USER+1)
...
WSAAsyncSelect(s, hWnd, WM_SOCKET, FD_READ|FD_WRITE);
7
네트워크 이벤트
네트워크 이벤트
의미
FD_ACCEPT
클라이언트가 접속하면 윈도우 메시지를 발생시킨다.
FD_READ
데이터 수신이 가능하면 윈도우 메시지를 발생시킨다.
FD_WRITE
데이터 송신이 가능하면 윈도우 메시지를 발생시킨다.
FD_CLOSE
상대가 접속을 종료하면 윈도우 메시지를 발생시킨다.
FD_CONNECT
접속이 완료되면 윈도우 메시지를 발생시킨다.
FD_OOB
OOB 데이터가 도착하면 윈도우 메시지를 발생시킨다.
8
윈도우 프로시저
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
....
}
 hwnd
 메시지가 발생한 윈도우
 msg
 WSAAsyncSelect() 함수 호출시 등록한 사용자 정의 메시지
 wParam
 네트워크 이벤트가 발생한 소켓
 lParam
 하위 16비트는 발생한 네트워크 이벤트, 상위 16비트는 오류 코드
9
코드 - 1
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
WSAAsyncSelect(sock, hWnd, MWM_SOCK, FD_ACCEPT|FD_CLOSE);
.
.
.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_CREATE:
On_Create(hWnd);
break;
case MWM_SOCK:
On_Socket(hWnd, (SOCKET)wParam, LOWORD(lParam), HIWORD(lParam));
break;
case WM_DESTROY:
On_Destroy();
}
return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}
10
코드 - 2
void On_Socket(HWND hWnd, SOCKET sock, WORD eid, WORD err)
{
switch(eid)
{
case FD_CLOSE:
On_Close(hWnd, sock, eid, err);
break;
case FD_ACCEPT:
On_Accept(hWnd,sock, eid, err);
break;
case FD_READ:
On_Recv(hWnd, sock, eid, err);
break;
}
}
11
WSAAsyncSelect() 사용시 유의할 점
– WSAAsyncSelect() 함수를 호출하면 해당 소켓은 자동으로 넌블
로킹 모드로 전환됨 : 블로킹 소켓은 윈도우 메시지 루프를 정지시
킬 수 있음
– Accept()함수가 리턴하는 소켓은 연결 대기 소켓과 동일한 속성을
지님 → 연결 대기 소켓은 직접 데이터 송수신을 하지 않으므로
FD_READ, FD_WRITE 이벤트를 처리하지 않음
• 그러나 accept() 함수가 리턴하는 소켓은 이벤트 처리를 해야하기 때
문에 WSAAsyncSelect() 함수를 다시 호출하여 속성 변경이 필요함
– 윈도우 메시지를 받았을 때 적절한 소켓 함수를 호출하지 않으면,
다음 번에는 같은 윈도우 메시지가 발생하지 않음
• ex) FD_READ 이벤트에 대응하여 recv()를 호출하지 않으면 동일한
소켓에 대한 FD_READ 이벤트는 더 발생하지 않음
12
WSAAsyncSelect() 사용시 유의할 점
수신버퍼
메시지 큐
SEND
FD_
CLOSE
READ
SEND
SEND
SEND
SEND
FD_
READ
\\\
SEND
.FD_READ는
.
.
FD_READ
send는 수신측이
발생시
수신
버퍼에
recv를
recv를수신
하지
send한번에
데이터가
않는다
보낸
있게
만큼만
되면
수신버퍼가
발생.
받게(않은
되는데
동시
꽉차지
1개
이후
이상
않으면
아직
발행하지
수신한
수행
완료
않음
데이 )
.결론적으로
송신측에서
수신측이
모든하더라도
recv를
수행하지
시점(데이터는
다 보냈
터가
있으면
다시 FD_READ는
발생.
지만)에
closesocket을
하게 되며
이런 경우에 FD_CLOSE가 발생을 하면 수신 버퍼
에 이직 recv하지 않은 것이 있는지 확인해야 한다.
13
WSAAsyncSelect() 사용시 주의할 점 – 수신버퍼 확인 하는 법
void On_Close(HWND hWnd, SOCKET sock, WORD eid, WORD err)
{
ULONG ulRecv;
if(ioctlsocket(sock, FIONREAD, &ulRecv) == 0)
{
if(ulRecv != 0)
{
PostMessage(hWnd, MWM_SOCK, (WPARAM)sock, eid);
}
else
{
closesocket(sock);
}
}
}
두번째 인자를 FIONREAD를 주고
세번째 인자에 ULONG타입인 변수의 주소를 주면
세번째 인자로 넘긴 주소에 아직 처리되지 않은 수신 버퍼에 있는 데이터
의 사이즈를 알 수 있음.
14
WSAAsyncSelect() 사용시 주의할 점
수신버퍼
SEND
SEND
메시지 큐
FD_
FD_
CLOSE
READ
FD_
FD_
CLOSE
READ
SEND
SEND
SEND
\\\
.남아
있는반복하다보면
수신버퍼의 처리보다
closesocket이
안 되기 때문에 메시지 큐
. 이를
결국은 수신할
데이터가 먼저
없게 이루어지면
되고
에 FD_CLOSE를
다시
발생 시켜줌으로써
먼저 시기가
FD_READ를
수행하게 되고 다시 남은 것이
closesocket을
정상적으로
수행할 수 있는
오게 됨.
있으면 당연히 FD_READ가 내부적으로 메시지 큐에 있게 됨.
15
Thank you
16