5.1 채팅 서버 구현 [TCP/IP 소켓 프로그래밍 with 윈도우즈]

먼저 포트 번호와 백로그 큐 크기 및 메시지 크기를 매크로 상수로 정의합시다.

진입점에서는 윈속을 초기화하고 대기 소켓을 설정한 후에 이벤트 처리하는 루프를 수행합니다. 그리고 윈속을 해제합니다.

대기 소켓을 설정하는 루틴은 차이가 없습니다.

소켓을 보관할 배열과 이벤트 핸들을 보관할 배열을 선언합니다. 그리고 현재 배열에 보관한 원소 개수를 기억할 변수도 선언합니다.

특정 소켓에 매핑할 네트워크 이벤트 개체를 생성하여 배열에 보관하는 함수를 정의합시다. 입력 인자로 소켓과 네트워크 이벤트 종류를 전달받습니다.

네트워크 이벤트 개체를 생성합니다.

그리고 소켓과 이벤트 개체 핸들을 배열에 보관합니다.

보관한 원소 개수를 1 증가합니다.

이제 제일 중요한 작업입니다. 소켓과 해당 이벤트 개체를 매핑하는 WSAEventSelect 함수를 호출합니다. 이함수를 호출하면 해당 소켓에 설정한 네트워크 이벤트가 발생하면 이벤트 개체를 신호 상태로 전이하도록 설정합니다.

이벤트 루프 함수를 작성합시다. 여기에서는 처리할 이벤트 종류로 연결 수락과 메시지 수신, 연결 종료가 있습니다.

제일 먼저 Listen 소켓에 클라이언트 연결 요청이 왔을 때 처리하기 위한 이벤트 개체를 추가합니다. 연결 요청에 관한 네트워크 이벤트 상수는 FD_ACCEPT입니다.

그리고 이벤트 처리 루프를 작성합니다.

이벤트 처리 루프에서는 제일 먼저 현재 이벤트 배열에 추가한 원소들 중에 신호 상태가 발생할 때까지 대기하는 작업을 수행합니다.

그리고 어떠한 이유로 신호상태로 바뀐 것인지 확인한다.

이제 네트워크 이벤트 종류에 따라 처리할 함수를 호출합니다.

이벤트 처리 루프가 끝나면 소켓을 닫습니다. 실제로 이벤트 처리 루프는 무한 루프이므로 이 코드까지 진행하지는 않습니다.

먼저 연결 요청에 관한 처리를 수행합시다.

클라이언트 연결 요청을 수락합니다.

WSAEventSelect에서는 최대 처리할 수 있는 소켓(이벤트) 수가 정해져 있어서 필터링 작업이 필요합니다.

연결 요청을 수락하여 반환한 송수신 소켓에 메시지 수신 혹은 연결을 닫으면 신호 상태로 전이할 네트워크 이벤트를 추가합니다.

확인할 수 있게 누가 채팅 방에 입장하였는지 콘솔 화면에 출력할게요.

이번에는 메시지를 수신하였을 때 처리하는 함수를 작성합시다.

먼저 메시지를 수신합니다.

수신한 클라이언트 정보를 확인합니다.

수신한 클라이언트 정보와 수신한 메시지 정보를 전송할 메시지 버퍼에 출력합니다.

채팅방에 접속한 모든 클라이언트에게 메시지를 전송합니다.

연결 종료 처리하는 함수를 작성합시다.

확인하기 쉽게 채팅 방을 나간 클라이언트 정보를 출력합시다.

소켓을 닫습니다.

그리고 네트워크 이벤트 개체를 닫습니다.

소켓 배열과 네트워크 이벤트 배열에서 해당 요소를 제거합니다. 여기에서는 맨 뒤에 원소를 지울 원소가 있는 위치에 덮어 씌우는 형태로 작성하였습니다.

채팅 방에 남아있는 나머지 클라이언트들에게 방을 나간 클라이언트 정보를 전송합니다.

다음은 이번 실습에서 작성한 채팅 서버 코드입니다.