사용법
1. IOCP핸들을 생성한다.
HANDLE CreateIoCompletionPort (
HANDLE FileHandle, // 목적하는 핸들.
HANDLE ExistingCompletionPort, // 연결할 IOCP의 핸들. 새로만들려면 NULL로 설정.
ULONG_PTR CompletionKey, // 핸들을 통한 작업이 끝났을때 IOCP는 이 컴플리션 키값을 넘겨준다.
DWORD NumberOfConcurrentThreads // 입출력 작업시 얼마나 많은 스레드를 사용할건지 설정. 0으로하면 시스템에서 알아서 잡아줌.
);
성공시 IOCP핸들을 반환. 실패시 0.
처음 생성시 인자로 INVALID_HANDLE, NULL, NULL, NULL를 넣어줌.
2. 핸들의 키와 쌍으로 IOCP핸들에 등록한다.
HANDLE CreateIoCompletionPort (
HANDLE FileHandle, // 목적하는 핸들.
HANDLE ExistingCompletionPort, // 연결할 IOCP의 핸들. 새로만들려면 NULL로 설정.
ULONG_PTR CompletionKey, // 핸들을 통한 작업이 끝났을때 IOCP는 이 컴플리션 키값을 넘겨준다.
DWORD NumberOfConcurrentThreads // 입출력 작업시 얼마나 많은 스레드를 사용할건지 설정. 0으로하면 시스템에서 알아서 잡아줌.
);
같은 함수를 사용해서 ExistingCompletionPort에 위의 생성한 IOCP핸들을 넣어준다. 연결된 IOCP핸들이 반환된다.
3. 핸들에 I/O 작업을 한다. (I/O작업을 신청한다는 의미가 더 어울릴 것 같다.)
IOCP는 중첩된(Overlapped)된 I/O방식을 사용한다.
따라서, WSASend(), WSARecv(), ReadFile(), WriteFile()를 사용할 것을 권한다.
보통의 IO함수랑 다른 차이점은 Overlapped구조체를 요구한다. 대부분 필요에 따라 구조체를 변형시켜서(상속, 포함)사용한다.
그리고 여기서 설정된 Overlapped구조체나 데이터들은 작업이 완료될때까지 변경되어서는 안된다.
비동기로 요청을 하였으므로 바로 반환된다. 그러므로 SOCKET_ERROR을 반환하지만 에러는 아니다.
반드시 GetLastError()로 조사를 하고 ERROR_IO_PENDING이 나오면 정상적인 비동기 작업이다.
4. 어떤 핸들에 대한 I/O작업이 완료되면 IOCP가 프로그램에게 알려준다.
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, // IOCP 핸들
LPDWORD lpNumberOfBytes, // 읽거나 쓰여진 바이트의 수
PULONG_PTR lpCompletionKey, // IOCP를 생성시 등록된 CompletionKey값을 반환
LPOVERLAPPED *lpOverlapped, // Overlapped 구조체
DWORD dwMilliseconds // 기다리는 시간. INFINITE로 무한대로 기다릴수 있음.
);
반환값은 FALSE라고해서 실패는 아니고. 반환되는 lpOverlapped구조체가 NULL이고 GetLastError()로 조사시 64의 값이 아닐때 에러란다-_-;
BOOL PostQueuedCompletionStatus (
HANDLE CompletionPort, // IOCP 핸들
DWORD dwNumberOfBytesTransferred, // 읽거나 쓰여질 바이트의 수
ULONG_PTR dwCompletionKey, // 등록할 CompletionKey값
LPOVERLAPPED lpOverlapped // Overlapped 구조체
);
IOCP가 반드시 파일이나, 네트웍의 전송으로만 사용되어야 할 필요는 없다.
스레드간의 통신에서도 이렇게 CompletionKey값을 주고받는것으로 대체 할 수도 있다.
5. 완료된 작업에 대해 해야 할 일을 한다.
수행된 내용의 다음 내용을 처리한다.
http://codesarang.com. mail to cpueblo
cpueblo.com