-
WSAEventSelect 모델개발/서버 2021. 11. 14. 22:55
select와 마찬가지로 한 스레드에서 최대 처리할 수 있는 이벤트 개수가 64개로 제한되기 때문에 많은 동접자를 처리해야 하는 서버에서는 쓰일 일이 없을 것 같습니다. 하지만 흐름을 알아두면 좋을 거 같아 정리합니다. 다음은 에코서버 예제입니다.
이벤트 객체 만들고 소켓과 연결
이벤트 객체와 세션은 벡터로 관리합니다. 실제로 세션은 아니지만 편한 관리를 위해 리스너 소켓과 이벤트 객체를 각 벡터의 0번째에 넣습니다. 그러고 나서 WSAEventSelect를 호출합니다. listenSocket에 연결할 listenEvent를 지정합니다. 이제부터는 listenEvent로 소켓의 상태를 판단할 수 있습니다.
신호 확인
WSAWaitMutipleEvent()는 세 번째 파라미터인 fWaitAll을 FALSE로 놓으면 두 번째 인수인 이벤트 객체 배열 중에서 단 하나라도 signaled 상태가 되면 해당 인덱스를 반환합니다. 여러 이벤트가 signaled 된다면 가장 작은 인덱스가 반환됩니다. 공식 문서를 보면 WSA_WAIT_EVENT_0를 빼줘야 한다고 나와 있습니다.
이벤트 확인
WSAEnumNetworkEvents()는 확인하고자 하는 소켓과 이벤트로 해당 이벤트가 어떤 상태의 이벤트인지 확인합니다. 주석에도 나와있듯 이 함수는 이벤트 객체의 상태를 non-signaled로 리셋하고 네트워크 기록을 초기화하기 때문에 꼭 WSANETWORKEVENTS 구조체 변수로 값을 받아둬야 합니다.
리스너 소켓 확인
앞서 리스너 소켓과 연결한 이벤트 객체는 FD_ACCEPT와 FD_CLOSE 상태를 관찰한다고 지정했습니다. 때문에 연결 확인을 위해서 networkEvents 변수의 해당 플래그를 확인합니다. 접속이 들어왔으면 클라이언트 소켓을 반환받고 이벤트 객체를 생성해 WSAEventSelelect()를 통해 연결합니다. 그러고 나면 신호 확인 부분에서 클라이언트가 보낸 요청을 감지할 수 있습니다.
클라이언트 소켓 확인
recv()와 send()의 반환값이 SOCKET_ERROR인데 WSAGetLastError()가 WSAEWOULDBLOCK이 아닌 경우라면 문제가 있는 상황이므로 해당 세션을 없애야 하는 부분이 있어야 합니다만 여기에선 다루지 않겠습니다.
'개발 > 서버' 카테고리의 다른 글
생각보다 쉽지만은 않은 SO_LINGER (0) 2019.10.22 [Hyper-V] 게스트에 고정 IP 주기 (4) 2019.09.02