모델 | 내용 |
Select 모델 | Select 모델은 동기 입출력을 수행하기 위해 필요한 경우 대기 중인 하나 이상의 소켓 상태를 결정한다. 소켓을 만들고, Select함수를 통해 FD_SET으로 해당 소켓을 등록하여 FD_ISSET으로 관찰할 수 있는 방식이다. fd_set -> Readfds – 수신할 데이터가 있을 때 Writefds – 쓰기 가능한 상태일 때, 연결 성공했을 때 Exceptfds – 연결이 실패했을 때 소켓모드와 상관없이 한 스레드에서 여러 소켓을 처리할 수 있고, 윈도우, 유닉스 등 여러 운영체제에서 사용할 수 있어서 이식성이 좋지만, 성능은 여섯 가지 모델 중 가장 좋지 않다. 64개 이상의 소켓을 처리하려면 여러 개의 스레드를 사용해야한다. |
WSAAsyncSelect 모델 | Async는 비동기적이라는 의미로 윈속의 소켓이벤트를 윈도우 메시지를 통해서 비동기적으로 받는다. 윈도우 메시지를 통해 성공 여부를 판단한다. 윈도우 메시지 큐에 의존해 소켓의 처리가 이루어져 많은 수의 소켓 이벤트를 처리해야 하는 경우 큐가 고갈될 수 있다. 윈도우 메시지를 사용자 정의하여 원하는 네트워크 이벤트를 발생시킨다. 네트워크 이벤트 FD_WRITE – WSAConnect 함수 호출하고 소켓이 처음 연결되었을 때, WSAAccept 호출 뒤 연결 수락되었을 때 send, WSASend, sendto, WSASendTO 함수 호출 후에 WSAEWOULDBLOCK이 리턴이 돼서 전송 버퍼가 비워졌을 때 이벤트 발생한다. 즉, 보낼 수 있는 상태가 되면 발생한다. FD_ACCEPT – 클라이언트가 접속했을 때 FD_READ – 수신 가능할 때 FD_CLOSE – 접속 종료할 때 FD_CONNECT – 접속 완료될 때 FD_OBB – 데이터가 도착할 때 소켓 이벤트를 윈도우 메시지 형태로 처리해서 윈도우 친화적이다. 서버보다 클라이언트에 유리하다. 하지만 하나의 윈도우 프로시저에서 일반 윈도우 메시지와 소켓 메시지를 처리해야 해서 성능저하의 요인이 된다. 또한 윈도우여야만 적용이 가능하다는 단점이 있다. |
WSAEventSelect 모델 | 두개 이상의 스레드가 협력해서 작업을 하는 경우에 상황에 따라 동기화가 필요하다. 그때 동기화 객체가 쓰이는데, event객체는 그 중 하나이며, 커널 오브젝트이기도 하다. 소켓과 WSACreateEvent()로 이벤트 객체를 생성하여 짝지어서 네트워크 이벤트가 발생함을 애플리케이션에서 알 수 있게 되는 방식이다. WaitForMultipleEvent() 함수로 신호 상태가 된 커널 오브젝트에 네트워크 이벤트가 발생했다는 사실을 알 수 있기 때문이다. 반환 값은 신호 상태로 변화된 이벤트 배열의 인덱스이다. 또한, WSAEnumNetworkEvents()로 구체적인 네트워크 이벤트를 알려주는 함수도 있다. Select 모델과 WSAAsyncSelect 모델의 특성을 혼합한 형태로 비교적 뛰어난 성능을 가짐에도 WSAAsyncSelect와 달리 윈도우 메시지가 아닌 이벤트 오브젝트를 사용해 윈도우가 아니어도 구현 가능하다. 단점으로는64개 이상의 소켓을 처리하려면 여러 개의 스레드를 사용해야한다. |
Overlapped 모델 I (Overlapped Event) |
Overlapped은 중첩 입출력으로 응용 프로그램은 입출력 함수를 호출한 후에도 입출력 작업의 완료 여부와 무관하게 다른 작업을 하는 비동기 입출력을 지원한다. IO가 여러개 중첩되는 것, 요청하고 기다릴 필요없이 리턴하고 다른 일을 수행하는 것이 Overlapped IO이고, 통지하는 방법에 따라 종류가 나뉜다. WSAEventSelect 모델과 비슷하게 이벤트 객체를 사용한다. 소켓 입출력 작업이 완료되면, 운영체제는 응용 프로그램이 등록한 이벤트 객체를 신호 상태로 바꾼다. 이벤트 객체를 관찰함으로써 입출력 작업 완료를 감지할 수 있다. 비동기 입출력을 지원하는 소켓을 생성하고 WSACreateEvent() 함수로 대응하는 이벤트 객체도 같이 생성한다. 비동기 입출력을 지원하는 소켓 함수를 호출할 때 WSAOVERLAPPED 구조체의 hEvent변수에 이벤트 개체 핸들 값을 넣어 전달한다. 동기 입출력이 완료가 되지 않았다면 오류를 리턴 하며. 오류 코드는 WSA_IO_PENDING으로 된다. 입출력이 완료가 되면 운영체제는 이벤트 객체를 신호 상태로 만들어 통보한다. WSAWaitForMultipleEvent() 함수가 리턴 되면 WSAGetOverlappedResult()함수로 비동기 입출력 결과를 확인하고 데이터를 처리한다. 비동기 입출력을 통해 성능이 뛰어나지만, 이벤트 객체로 64개 이상의 소켓을 처리하려면 여러 개의 스레드를 사용해야 하는 단점이 있다. |
Overlapped 모델 II (Overlapped Callback) |
소켓 입출력이 완료되면 등록해둔 함수를 자동으로 호출한다. 일반적으로 운영체제가 호출하는 응용 프로그램 함수를 콜백함수라고 하는데, Overlapped 모델에서는 완료 루틴(completion routine) 이라고 한다. 비동기 입출력을 지원하는 소켓을 생성한다. 비동기 입출력 함수(WSASend, WSARecv)를 호출할 때 완료 루틴의 시작 주소를 함수 인자로 전달한다. 비동기 입출력 작업이 완료되지 않으면 WSA_IO_PENDING이 된다. 운영체제에 입출력 작업요청을 한다. WaitForSingleObjectEx(), WaitForMultipleObjectEx(), SleepEx(), WSAWaitForMultipleEvent() 등 함수로 해당 스레드는 완료 루틴이 호출될 수 있는 상태인 Alertable wait 상태로 진입하게 한다. 비동기 입출력 작업이 완료되면, 운영체제는 스레드의 APC큐에 결과를 저장하고 완료 루틴을 호출한다. APC 큐 : asynchronous procedure call queue는 비동기 입출력 결과를 저장을 위해 운영체제가 각 스레드에 할당하는 메모리 영역이다. 비동기 입출력 함수를 호출한 스레드가 Alertable wait 상태에 있으면 운영체제는 APC 큐에 저장된 정보를 참조하여 완료 루틴을 호출한다. 완료 루틴 호출이 끝나면, 스레드는 Alertable wait 상태에서 빠져나온다. 스레드가 비동기 입출력 결과를 계속 처리하기 위해서 다시 Alertable wait 상태에 진입하는 동작 원리를 갖는다. 장점으로는 비동기 입출력을 통해 뛰어난 성능을 갖는다. 단점으로는 모든 비동기 소켓 함수에 대해 완료 루틴을 사용할 수 있는 건 아니다. 콜백 함수의 결과를 해당 콜백 함수를 수행한 스레드 만이 알 수 있다. |
IOCP Completion Port |
비동기 입출력으로 입출력을 요청하고도 다른 일을 수행하는 것이 Overlapped IO이다. 이 Overlapped IO를 이벤트와 콜백을 사용해 작업완료 여부를 체크하는 방법 중 하나로 윈도우에서 제공하는 일반적인 I/O 모델 중 최고 성능을 갖는 IOCP이다. 커널 객체(운영체제의 핵심적인 기능 프로세스, 스레드 메모리 관리 기능 제공하는 객체)이다. IOCP 시스템을 관리하는 객체를 커널이 만들어서 우리에게 HANDLE를 넘겨주는 것이다. IOCP 특징 중 하나가, 쓰레드 풀로 쓰레드를 재사용하는 것인데, IOCP 본인의 스레드 큐를 가지고 작업을 하고 완료된 IO가 있다면 알려준다. 재사용이 가능한 스레드를 유지하는 스레드 풀링은 WSASend/ WSARecv같은 비동기 입출력 함수를 쓰면 스레드 내부적으로 APC 큐가 생성이 된다. 여기에 완료된 결과를 저장하는데 APC큐는 자동으로 생성되고 파괴된다. 그리고 그 큐는 본인 스레드에서만 확인이 가능하는데, 반면에 관리자 역할을 하는 IOCP는 모든 걸 확인이 가능하며, CloseHandle()함수 호출하여 파괴한다. 입출력 완료 포트를 접근하는 스레드를 별도로 두는데 이를 작업 스레드(WorkerThread라고 한다.) 예를 들어 관리자(IOCP)가 일꾼(1번 입출력), 일꾼(2번 입출력) 중 1번 일꾼의 IO작업이 끝났 다하면 이를 처리하기 위해 Waiting Thread Queue에 가장 최근에 들어온 스레드를 깨운다. I/O가 완료될 때마다 기다리고 쓰레드가 알아서 I/O작업을 해 성능이 좋다. -> 스레드 풀 또한, 특정 스레드에서 작업을 하던 간에IOCP 큐자체가 기타 스레드 결과가 저장이 된다. 즉, A 스레드에서 작업해도 B스레드에서도 확인이 가능하다. |
IOCP 자료구조 | 설명 |
Device list | hDevice, Completion Key로 구성되어 키 값으로 값을 얻을 수 있게 됨 |
IO Completion Queue | FIFO로 앞에서부터 자료를 빼서 처리, I/O가 완료 되면 정보(이벤트)를 저장함 |
Waiting Thread Queue | LIFO로 마지막에 사용된 스레드를 다시 사용함, 스레드 ID가 저장됨 스레드 풀 역할 |
Released Thread List | Waiting Thread Queue(스레드 풀)에서 꺼내 온 쓰레드 정보 |
Paused Thread List | Release쓰레드가 Suspend상태되면 저장되고, Suspend상태가 해제되면 다시 Released Thread List로 올라감 |
소켓 입출력 모델 (Select, WSAAsyncSelect, WSAEventSelect는 동기 입출력과 비동기 통지를 결합한 형태
비동기 소켓 입출력 모델은 (Overlapped, Completion Port)는 비동기 입출력과 비동기 통지를 결합한 형태