이번에는 WSAEventSelect 이용한 멀티플렉싱을 살펴봅시다.
채팅 서버는 클라이언트로부터 메시지를 수신하면 채팅 방에 접속한 모든 클라이언트에게 메시지를 전달해 주어야 합니다. 이와 같은 처리를 위해서는 채팅 방에 접속한 전체 클라이언트 정보를 기억하고 있어야 합니다.
특히 채팅 서버에서는 별도의 쓰레드없이 Listen 소켓에 클라이언트의 연결 요청이 있는지와 클라이언트로부터 수신한 메시지가 있는지 확인하는 작업이 필요합니다.
WSAEventSelect 모델은 특정 소켓에 특정 사건이 발생하였는지 확인하기 위한 이벤트 개체를 만들어 처리하는 모델입니다. 채팅 서버를 예를 들면 Listen 소켓에 연결 요청이 있을 때 신호 상태로 전이할 이벤트 개체를 생성합니다.
그리고 반복문에서 현재까지의 이벤트 개체들 중에 하나라도 신호 상태로 전이할 때까지 대기합니다. 대기 상태가 끝나면 어느 이벤트 개체가 신호 상태인지 확인하여 해당 소켓에 준비한 사건을 처리합니다. 그리고 다시 반복합니다.
만약 Listen 소켓과 매핑한 이벤트 개체가 신호 상태이면 클라이언트의 연결 요청을 수락합니다. 그리고 수락(accept) 함수가 반환한 송수신 소켓에 메시지 수신 혹은 소켓 닫기 이벤트가 발생할 때 신호 상태로 전이할 이벤트 개체를 생성합니다. 물론 새로 생성한 이벤트 개체는 반복문에서 대기하는 이벤트 개체 집합에 추가합니다.
만약 송수신 소켓과 매핑한 이벤트 개체가 신호 상태이면 신호 상태로 전이한 이유가 메시지 수신 때문인지 소켓 닫기 때문이지 확인합니다. 메시지 수신 때문이면 recv 함수를 호출하여 메시지를 수신한 후에 채팅 방에 접속한 모든 클라이언트에게 메시지를 send 합니다. 그리고 다시 반복문의 대기 구문을 수행합니다.
그리고 송수신 소켓과 매핑한 이벤트 개체가 신호 상태이고 신호 상태로 전이한 이유가 소켓 닫기 이벤트일 때는 해당 소켓을 닫고 매핑한 이벤트 개체를 제거하고 대기하는 이벤트 개체 집합에서도 제거합니다. 그리고 다시 반복문의 대기 구문을 수행합니다.