코드를 보면서 Overlapped I/O를 다루는 방법을 알아봅시다.
1. Overlapped I/O를 걸 때 ‘진행 중인 상태 현황’을 보관하는 구조체를 먼저 준비합시다(➊).
2. 블로킹 소켓을 그대로 사용합니다.
3. 소켓에 대한 Overlapped I/O 전용 함수를 호출합시다(➋). 전용 함수는 항상 즉시 리턴합니다.
4. 즉시 성공했다면 OK가 리턴되고(➌), 그렇지 않으면 완료를 기다리는 중, 즉 I/O pending이라는 값이 즉시 반환됩니다(➍).
5. Overlapped I/O 완료 여부는 ➎처럼 확인하는 함수를 호출해 보면 알 수 있습니다.
6. ➎에서 ‘완료’라고 결과가 나오면 그냥 나머지 처리를 합시다.
7. Overlapped I/O를 수신했다면 data 객체에 수신된 데이터가 자동으로 채워져 있을 것입니다. 이를 그냥 액세스합니다.
Overlapped I/O는 논블록 소켓과 비교했을 때 앞서 두 가지 이유로 성능상 유리합니다. 하지만 대가가 따릅니다. 바로 백그라운드에서 액세스로 인한 주의 사항입니다.
Overlapped I/O 함수는 즉시 리턴되지만, 운영체제로 해당 I/O 실행이 별도로 동시간대에 진행되는 상태입니다. 놀랍게도 운영체제는 소켓 함수에 인자로 들어갔던 데이터 블록을 백그라운드에서 액세스합니다. 여러분 코드가 뭔가를 하고 있는데, 이와 별개로 운영체제가 마음대로 여러분 데이터를 건드리고 있다는 말입니다! 이름 그대로 중첩된(overlapped) 것이지요.
따라서 여러분이 호출한 Overlapped I/O 전용 함수가 비동기로 하는 일이 완료(complete)될 때까지는 소켓 API에 인자로 넘긴 데이터 블록을 제거하거나 내용을 변경해서는 안 됩니다. 그뿐만 아니라 Overlapped I/O 전용 함수의 인자로 Overlapped status 구조체가 같이 들어가는데, 완료 여부는 이 구조체로 알 수 있습니다.