IOCP 는 Input Output Completion Port 즉 Input/Output 작업이 completion 되었을 때 port 를 통해서 일을 처리하는 것입니다.
동기식
- send나 recv 함수가 완료되기 전에는 실행 코드가 움직이지 않는다.
비동기식
- send나 recv 는 우선 운영체제에게 소켓 작업을 한다고 알려주고 후에 완료 통지를 받는 방식이다.
중첩 소켓
- 여러 개의 소켓 입출력 작업이 운영체제로 들어가면 몇 개는 입출력 시간이 겹쳐도 작업이
가능하다는 매우 획기적인 기술입니다.
- 중첩되는 시간만큼 속도가 빨라진다는 장점을 가지고 있습니다.
비동기 I/O가 완료되면 정보단위가 만들어지고 이것이 IOCP 큐에 들어갑니다. 이 때 작업 스레드는 IOCP의 통지를 받고 IOCP큐에서 정보 단위 하나를 가져와 작업을 수행하게 됩니다.
IOCP는 하나의 스레드가 하나 이상의 사용자로부터의 요구를 처리할 수 있도록 해준다. 꼭 한개의 스레드를 사용하는 건 아니다. 상황에 맞게 스레드의 개수를 조절 할수 있다.
작업 스레드가 많으면 좋지만, 스레드가 많게 되면 context switching이 많이 일어나므로 적은 수의 스레드를 사용한다.
IOCP동작 구도에 대하여 설명 드리겠습니다.
CreateIoCompletionPort함수를 통해 IOCP를 처음 생성하고 프로세서 개수 만큼 Thread를 생성해 줍니다.
서버를 만들어 클라이언트가 접속 하기를 기다립니다. 후에 클라이언트가 접속해서 그림에 보이는 것과 같이 1,2,3번의 패킷을 서버에 보내면 CompletionQueue에 순차적으로 대기를 하게 되고 대기되어 있는 패킷이 현재 수행하고 있지 않는 Thread를 찾아 수행하도록 합니다. 그리고 Thread에서의 일이 끝나고 패킷이 아직 할 일이 있다면 시스템에 알려준뒤 Completion Queue뒤로 가서 다시 대기를 하게 되고 사용한 Thread는 다음 대기 하고 있던 패킷이 일을 수행하게 됩니다.
IOCP의 가장 큰 장점은 쓰레드 풀을 통한 context switching 비용이 줄어듭니다. 단점은 윈도우 NT 이상 즉 윈도우 2000 이상에서만 지원한다는 점이 있습니다.
CreateIoCompletionPort 함수는 2가지 역할을 합니다.
- 개체 생성
- 소켓 연결
자세한 사항은 Ex 부분을 보시거나 예제 코드를 보면서 확인해주시면 되겠습니다.
Completion Queue에 해당 명령어가 있는지 확인하는 함수입니다.
IOCP 개체를 생성하게 되면 Completion Queue 는 한개만 만들어집니다. 이 큐안에 완료된 명령어가 있다면 쓰레드들이 경쟁을 통해 명령어를 가져가 실행을 하게 됩니다.
SYSTEM_INFO 는 구조체이며 GetSystemInfo()를 씀으로써 시스템의 정보를 가져오게 됩니다.
우리는 시스템의 프로세서 수를 알아내기 위해 이 함수를 사용하였습니다.
마지막으로 예제를 보여드리겠습니다.
IOCP를 이용한 파일 전송 프로그램입니다.
CreateIoCompletionPort 를 이용해서 개체를 생성하고
SYSTEM_INFO 를 이용해서 시스템프로세서 수를 불러왔습니다.
이때 for문안에 보면 sinfo.dwNumberOfprocessors*2 로 되어있는대 이건 마이크로소프트에서
권장 사항이 CPU의 *2 배수만큼 쓰레드를 생성하기 위해서입니다.
CreateIoCompletionPort를 이용해서 소켓을 연결하는 부분.
쓰레드 내에서 실행하는 명령어로
완료 큐에 완료된 명령어가 있는지 확인하는 함수입니다.
실패시 0 반환.