포스트

[네트워크] IOCP의 개념

이 포스트는 “게임 서버 프로그래밍 교과서”를 참고하여 작성된 포스트입니다.
개인 학습을 기록한 내용을 담고 있어 추후 수정될 예정입니다.


epoll은 리눅스에서 대량의 논블로킹 소켓을 효율적으로 처리해 주는 API 였습니다.
윈도우에서는 epoll 대신 IOCP 라는 API를 사용하여 대량의 소켓을 관리합니다.
이번 포스트에서는 IOCP의 개념이 무엇인지 살펴보겠습니다.


입출력 완료 포트 IOCP란

IOCP(Input Output Completion Port)는 윈도우에서 사용하는 고성능 API로
Overlapped I/O와 함께 사용합니다.

IOCP는 소켓에 걸어둔 Overlapped I/O가 완료되면 이를 감지하여 사용자에게 전달하기 위해
내장된 큐(Queue)에 완료 신호를 넣으면 사용자는 이를 꺼낼(Pop) 수 있습니다.

큐를 사용하기 때문에 소켓의 개수가 1만개 이상이라고 하더라도
1만개 이상의 소켓 중 I/O가 완료된 소켓만 IOCP를 이용해 바로 얻을 수 있기 떄문에
Selec처럼 모든 소켓에 대해 반복문을 실행하지 않아도 됩니다.


IOCP와 EPoll

IOCP의 동작은 리눅스의 EPoll과 유사하지만 몇 가지 차이점이 존재합니다.
먼저, EPoll은 사용자에게 I/O 가능인 것을 알려주지만
IOCP는 사용자에게 I/O 완료인 것을 알려줍니다.

실행 과정 외에도 IOCP는 EPoll 보다 오래된 API이기 때문에 사용방법이 비교적 복잡합니다.
복잡한 사용방법 중 하나가 바로 Accept 과정에서 사용하는 AcceptEx가 있습니다.

AccpetEx의 경우, 일반적인 Accept와 다르게 listen 소켓과
Accept에 성공한 뒤 새로운 소켓을 할당할 또 다른 소켓을 전달해줘야 합니다.

또한 여기서 사용되는 소켓은 Overlapped I/O가 걸린 상태여야 합니다.


반대로 IOCP가 EPoll에 비해서 성능상 유리한 기능도 있습니다.
IOCP는 여러 쓰레드를 모아두고 필요할 때 꺼내서 사용할 수 있는 쓰레드 풀
EPoll 보다 비교적 쉽게 구현할 수 있습니다.


IOCP는 어떤 소켓에 대해 Overlapped I/O를 하지 않는 이상 그 소켓에 대한 완료 신호는 발생하지 않습니다.
즉, 한 소켓에 대한 완료 신호를 한 스레드만 처리할 수 있게 보장됩니다.
이러한 특징 덕분에 IOCP 하나를 여러 스레드가 동시에 기다리도록 구현하기 쉽습니다.
또한 많은 소켓에 대한 I/O 처리를 동시다발적으로 수행할 때, 여러 스레드가 완료 신호 처리를
골고루 나눠서 처리할 수 있습니다.


반면 EPoll에서는 I/O 완료 신호가 아닌 I/O 가능 이벤트가 들어옵니다.
여기서 EPoll은 IOCP와 다르게 한 소켓을 한 스레드가 처리라는 것이 불가능하기 때문에
같은 소켓에 대해 여러 쓰레드가 동시에 가져갈 수 있습니다.
따라서 어느 것을 먼저 처리하고 어느 것을 나중에 처리해야 하는지 정하는 로직이 필요하므로
비교적 복잡해집니다.


IOCP와 EPoll의 장단점 비교

구분IOCPEPoll
블로킹을 없애는 수단Overlapped I/O논블로킹 소켓
논블로킹 처리 순서1. Overlapped I/O 걸기
2. 완료 신호 꺼내기
3. 꺼낸 완료 신호 처리
4. 처리 후 다시 Overlapped I/O 걸기
1. I/O 이벤트 꺼내기
2. 꺼낸 이벤트에 대응하는
소켓에 대한 논블로킹 I/O 실행
지원 플랫폼윈도우리눅스, 안드로이드
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.