1. 비동기 Notification의 의미
인터넷 계층
Link계층 : 물리 + 데이터링크
IP계층
TCP/UDP계층 : 송수신 버퍼가 생성된다.
응용프로그램 계층
동기화된 입력 및 출력 함수의 호출
동기화 : 함수의 호출과 행위의 시작, 함수의 리턴과 행위의 종료가 일치함.
데이터 전송 종료 : Application -> TCP계층으로 데이터를 다 보낸 상황. send함수를 호출하면 출력버퍼로 보내고자 하는 데이터가 다 들어갔을 때의 상황.
데이터 수신 종료 : TCP -> Application으로 데이터를 다 읽은 상황.
동기화된 데이터 입출력 과정상의 문제점
※ Host B의 버퍼가 꽉 찼을 경우에 (패킷 전송 일시 정지 요청에 의해) Host A는 패킷 전송을 하지 않고 blocking상태에 있게 된다.
※ send함수에서 패킷을 다 보냈을 경우 send함수가 리턴되어 종료된다.
비동기화 Notification
동기화 Notification
1. select 함수를 기반으로 한 서버의 구현
2. 핸들에 변화가 발생해야 리턴한다. select 함수의 리턴 시기와 핸들 변화 시기가 일치(동기)
비동기화 Notification
1. WSAEventSelect 함수를 기반으로 한 서버의 구현
2. 함수의 호출과 동시에 리턴한다. 따라서 핸들의 변화를 확인하기 위한 별도의 과정이 필요하다.
20.2 WSAEventSelect 모델 기반 서버 구현을 위한 API
구현순서
※ 소켓과 소켓을 위한 Event Object(소켓의 상태를 반영)가 쌍을 이룬다. 소켓의 변화가 다양하기 때문에 Event 객체가 따로 필요하다.
1. WSACreateEvent : Event를 편하게 이용할 수 있도록 돕는다.
2. WSAEventSelect
select함수 : 관심을 두고자 하는 핸들을 설정(설정) + 소켓의 변화(알림), 동기화 알림 함수.
WSAEventSelect : 관심을 두고자 하는 하나의 핸들을 설정만 할 수 있음.
3. WSAWaitForMultipleEvents : 소켓의 변화를 확인. nonsignaled에서 signaled로 변화할 때 리턴됨.
4. WSAEnumNetworkEvents : 소켓이 변화된 이유를 확인.
필요한 함수
WSAEVENT WSACreateEvent(void);
리턴 : manual-reset 모드, non-signaled 상태의 이벤트
int WSAEventSelect(
SOCKET s, // 감시 대상이 되는 소켓
WSAEVENT hEventObject, // 소켓의 변화를 확인하기 위한 이벤트 오브젝트의 핸들.
long lNetowrkEvents // 감시하고자 하는 이벤트 종류를 Bit-wise OR(|)로 묶어서 전달
);
리턴 : 성공시 0, 실패시 SOCKET_ERROR
감시하고자 하는 이벤트 종류
이벤트 | 의미 |
FD_READ | 수신된 데이터가 존재할 경우 |
FD_WRITE | 블로킹되지 않고 데이터를 전송할 수 있는 경우 |
FD_OOB | OOB 메세지 수신에 대한 이벤트 |
FD_ACCEPT | 연결 요청이 수신되었을 경우 |
FD_CLOSE | 연결 종료 요청이 수신되었을 경우 |
DWORD WSAWaitForMultipleEvents(
DWORD cEvents, // 검사 대상의 핸들 수
const WSAEVENT FAR *lphEvents, // 검사 대상의 배열
BOOL fWaitAll, // FALSE일 경우 하나의 배열만 변화가 있어도 리턴. TRUE면 모든 배열의 변화가 있어야 함.
DWORD dwTimeout, // 타임아웃.
BOOL fAlertable
);
여러 개의 이벤트 핸들(포인터로 배열 전달)이 signaled 상태가 되었는지 감시하는 함수.
리턴 : 실패시 WAIT_FAILED 리턴, 성공시 이벤트 발생 오브젝트 정보 리턴
int WSAEnumNetworkEvents(
SOCKET s, // 소켓
WSAEVENT hEventObject, // 이벤트가 발생한 소켓과 연결되어 있는 이벤트 오브젝트 핸들
LPWSANETWORKEVENTS lpNetworkEvents // 발생한 이벤트 정보와 오류 정보로 채워진 WSANETWORKEVENTS 구조체 포인터
);
이벤트 핸들이 발생한 이유를 알아내는 데 사용한다. signaled 상태의 이벤트 핸들을 nonsignaled상태로 바꿔주는 기능도 수행한다.
리턴 : 성공시 0, 실패시 SOCKET_ERROR 리턴
발생한 이벤트 정보와 오류 정보로 채워진 WSANETWORKEVENTS 구조체
typedef struct _WSANETWORKEVENTS{
long lNetworkEvents;
int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;
※ bind와 listen 사이의 소켓에 대해 이벤트를 만든다.
index = WSAWaitForMultipleEvents(sockTotal, hEventArray, FALSE, WSA_INFINITE, FALSE);
index = index - WSA_WAIT_EVENT_0;
여러 개의 소켓에서 변화가 일어났는 지 확인하고 소켓의 index값을 얻는다. 리턴된 index값은 가장 작은 소켓 인덱스 값이다.
변화가 일어난 소켓이 여러개일 수 있기 때문에 각각을 for문을 통해 확인한다.
'네트워크 프로그래밍' 카테고리의 다른 글
[TCP/IP 소켓 프로그래밍] 22. Completion Port 입출력 모델 (0) | 2009.09.11 |
---|---|
[TCP/IP 소켓 프로그래밍] 21. Overlapped 입출력 모델 (0) | 2009.09.11 |
[TCP/IP 소켓 프로그래밍] 19. 윈도우즈 기반 쓰레드 동기화 (0) | 2009.08.24 |
[TCP/IP 소켓 프로그래밍] 18. 윈도우즈 기반 쓰레드 사용하기 (0) | 2009.08.20 |
[TCP/IP 소켓 프로그래밍] 17. 프로세스(Process)와 쓰레드(Thread) (0) | 2009.08.19 |