본문 바로가기

카테고리 없음

IOCP서버의 흐름을 이해해보자

IOCP를 이용하여 비동기를 처리하는 IOCP 서버는 어떤 식으로 동작이 될까? Accept를 예로 한 번 알아보자.

 

 

낚시를 이용한 비유


이해를 쉽게 하기 위해 우리는 accept활동을 낚시에 비유할 것이다.

낚시는 3가지 과정으로 이루어져 있다.

  1. 낚싯대 세팅 후 던지기
  2. 물고기 기다리기
  3. 물고기가 잡히면 그 후 물고기 처리

이것을 서버에 적용해 보면

  1. 소켓을 Completion port에 세팅하고, 비동기 입출력 진행하기
  2. 입출력 완료 기다리기
  3. 입출력이 완료되면 해당 입출력에 맞춰 후처리 하기

IOCP는 비동기 입출력을 할 때 Overlapped 오브젝트와 소켓을 completion port에 넣을 때 key값으로 정보를 전달할 수 있다.

key값을 통해 socket의 정보를 담은 객체(여기선 Session이라고 부르겠다)를 통해 후처리 함수를 실행시켜주면 된다.

또한 overlapped오브젝트를 통해 어떤 입출력인지 정보를 담아 입출력에 따른 함수를 호출해 줄 수도 있다.

 

 

그림을 보면 낚시 준비를 한 낚시꾼(세팅된 소켓)이 낚싯대를 던져놓았고(비동기 Accept 실행), 낚싯대에 물고기가 걸리자(스레드가 IO를 완료하자), 물고기의 종류(overlapped에 저장된 IO Type)에 따라 알맞은 초밥을 만들었다.(후처리 함수)

 

주의점


낚시는 한 번으로 끝나면 안된다.

이대로 로직을 끝낸다면, 그냥 한 명의 클라이언트를 받는 것에 그치는 로직이 된다. 하지만 우리의 목표는 여러 명의 접속, 송신, 수신을 비동기로 처리하는 서버이다.

그것을 위해선 낚싯대를 통해 처리를 한 것으로 끝나는 것이 아닌, 낚시대를 다시 던져 주어야 한다.

 

OnAccept함수에 다시 Register를 하는 함수를 실행시켜 준다면, Accept -> 후처리 -> Accept의 무한굴레를 만들 수 있다. 이로써 무한하게 유저를 받을 수 있는 서버가 완료되었다.

낚싯대가 끊어질 때 예외 처리가 필요하다.

 

물고기를 잡은 후, 물고기로 초밥을 만들기 위해 끌어올리던 중 낚시대가 끊어질 수 있다. 

서버에서도 마찬가지로 입출력이 완료됐지만, 후처리 함수를 실행 중 오류가 발생할 수 있다. 

 

후처리함수에서 예외처리를 할 때 다시 낚싯대를 던져주는 작업(Register)을 무조건 진행해 주자.

물고기를 한 번에 여러 마리 잡으려면 낚싯대를 여러 개 던져주어야 한다.

 

 

아직 한 마리의 물곡기를 처리하지 못했는데 물고기가 바글바글하다면, 나머지 물고기는 놓치거나, 잡으려면 많은 시간이 필요하다. 이를 해결하기 위해선 여러 개의 낚싯대를 던져주면 된다.

 

Register를 3번 해주면 3개의 클라이언트를 동시에 받을 수 있다. 동접이 많아지면 한 개의 클라이언트가 처리되는 동안 다른 클라이언트가 못 들어오는 경우가 발생하지 않도록 하자.

 

마무리


이러한 작업은 Accept 뿐만 아니라 Recv와 Send와 같은 다른 입출력에서도 사용된다. 똑같은 흐름으로 Async Recv를 completion port에 등록해 주고, 완료되면 후처리 함수와 함께 다시 등록을 하는 식으로 진행하면 된다!