1 IOCP 만들기
HANDLE CreateIoCompletionPort (
HANDLE FileHandle,
HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads
);
이름 그대로 IOCP를 만들어 주는 함수 이다. 처음 IOCP를 만들 때는 네개의 인자 모두를 사용하는 것이 아니라 처음의 한개 인자만을 사용한다.그냥 단순히 IOCP를 생성하기만 하는 것 이므로,
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
와 같이 생성하면 된다.
이제 IOCP를 생성했으므로, 앞에서 말했던 것 처럼 이 IOCP를 통해 입출력 완료가 일어난 결과를 통보 받기만 하면 된다.
결과를 통보 받는다 하여 사용자에게 이벤트나 기타의 방법으로 알려 주는 것이 아니다. IOCP는 입출력 완료가 일어나면 그 결과를 특정한 큐에 집어 넣어 둔다. 때문에 사용자는 이 큐를 항상 감시 하고 있어야 한다. 이 큐에 먼가가 들어 오게 되면 입출력 작업중 하나가 완료 된 것이다. 그럼, 이 큐를 감시할 스레드를 만들어야 할 것이다. 보통은 이 스레드를 작업자 스레드(WorkerThread)
라 부른다.
_beginthreadex(NULL, 0, WorkerThread, , (LPVOID)hIOCP, 0, NULL);
작업자 스레드까지 생성 했으므로, 실제로 입출력을 할 FileHandle을 만들어야 한다. 우리는 소켓을 통해 입출력을 할 것 이므로 소켓을 생성해 주면 된다. 물론 파일 핸들을 통해서도 네트웍입출력이 가능하긴하 지만 그냥 편하게 소켓을 사용하자.
소켓을 생성할 때 주의할 것은 이 소켓이 Overlapped가 가능한 소켓이어야 한다는 것 이다. 그냥 일반적으로 소켓을 생성하면 Overlapped가 가능한 소켓이 된다. Winsock2의 WSASocket()을 사용하여 처음 소켓을 만들때 Overlapped 인자를 주어 소켓을 생성할 수도 있다.
SOCKET hSocket = WSASocket(AF_INET, SOCKET_STREAM, 0, NULL, WSA_FLAG_OVERLAPPED);
이제 이 소켓을 IOCP에 연결 해 준다. 그럼 이 소켓에서 입출력 완료가 일어났을 때 완료 통보가 완료큐에 들어가게 되고, 그럼 이 완료큐를 감시하고 있던 스레드에서 그 결과를 가져와서 해당 작업을 할 수있게 되는 것 이다.
CreateIoCompletionPort((HANDLE)hSocket, hIOCP, CompletionKey, 0);
IOCP를 만들고, 스레드를 만들었고 소켓을 만들어 IOCP에 등록까지 마쳤다. 이제 소켓을 통해 입출력 작업을 하면 된다. 그러면 입출력 작업이 완료 되었을 때 우리는 그 결과를 가져 올 수 있을 것 이다.
그럼, 입출력이 완료 되었을 때 완료 큐에서 결과를 가져 오는 방법을 알아야 할 것 이다.
GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED *lpOverlapped,
WORD dwMilliseconds
);
완료 큐에서 결과를 가져오는 함수 이다. 대충 인자를 살펴보아도 무슨 역할을 하는 지 알 수 있을 것 이다.
자 이제 이것으로 준비는 모두 끝 났다. 이것을 바탕으로 가장 기본적인 IOCP Echo Server를 만들어 보도록 하자.
HANDLE CreateIoCompletionPort (
HANDLE FileHandle,
HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads
);
이름 그대로 IOCP를 만들어 주는 함수 이다. 처음 IOCP를 만들 때는 네개의 인자 모두를 사용하는 것이 아니라 처음의 한개 인자만을 사용한다.그냥 단순히 IOCP를 생성하기만 하는 것 이므로,
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
와 같이 생성하면 된다.
이제 IOCP를 생성했으므로, 앞에서 말했던 것 처럼 이 IOCP를 통해 입출력 완료가 일어난 결과를 통보 받기만 하면 된다.
결과를 통보 받는다 하여 사용자에게 이벤트나 기타의 방법으로 알려 주는 것이 아니다. IOCP는 입출력 완료가 일어나면 그 결과를 특정한 큐에 집어 넣어 둔다. 때문에 사용자는 이 큐를 항상 감시 하고 있어야 한다. 이 큐에 먼가가 들어 오게 되면 입출력 작업중 하나가 완료 된 것이다. 그럼, 이 큐를 감시할 스레드를 만들어야 할 것이다. 보통은 이 스레드를 작업자 스레드(WorkerThread)
라 부른다.
_beginthreadex(NULL, 0, WorkerThread, , (LPVOID)hIOCP, 0, NULL);
작업자 스레드까지 생성 했으므로, 실제로 입출력을 할 FileHandle을 만들어야 한다. 우리는 소켓을 통해 입출력을 할 것 이므로 소켓을 생성해 주면 된다. 물론 파일 핸들을 통해서도 네트웍입출력이 가능하긴하 지만 그냥 편하게 소켓을 사용하자.
소켓을 생성할 때 주의할 것은 이 소켓이 Overlapped가 가능한 소켓이어야 한다는 것 이다. 그냥 일반적으로 소켓을 생성하면 Overlapped가 가능한 소켓이 된다. Winsock2의 WSASocket()을 사용하여 처음 소켓을 만들때 Overlapped 인자를 주어 소켓을 생성할 수도 있다.
SOCKET hSocket = WSASocket(AF_INET, SOCKET_STREAM, 0, NULL, WSA_FLAG_OVERLAPPED);
이제 이 소켓을 IOCP에 연결 해 준다. 그럼 이 소켓에서 입출력 완료가 일어났을 때 완료 통보가 완료큐에 들어가게 되고, 그럼 이 완료큐를 감시하고 있던 스레드에서 그 결과를 가져와서 해당 작업을 할 수있게 되는 것 이다.
CreateIoCompletionPort((HANDLE)hSocket, hIOCP, CompletionKey, 0);
IOCP를 만들고, 스레드를 만들었고 소켓을 만들어 IOCP에 등록까지 마쳤다. 이제 소켓을 통해 입출력 작업을 하면 된다. 그러면 입출력 작업이 완료 되었을 때 우리는 그 결과를 가져 올 수 있을 것 이다.
그럼, 입출력이 완료 되었을 때 완료 큐에서 결과를 가져 오는 방법을 알아야 할 것 이다.
GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED *lpOverlapped,
WORD dwMilliseconds
);
완료 큐에서 결과를 가져오는 함수 이다. 대충 인자를 살펴보아도 무슨 역할을 하는 지 알 수 있을 것 이다.
자 이제 이것으로 준비는 모두 끝 났다. 이것을 바탕으로 가장 기본적인 IOCP Echo Server를 만들어 보도록 하자.
'공부 해 Boa요. > Network' 카테고리의 다른 글
Raw Socket (0) | 2006.09.29 |
---|---|
Consol Echo Client (0) | 2006.09.27 |
실전 네트웍 프로그래밍 - 4 - IOCP Echo Server (0) | 2005.06.29 |
'실전 네트웍 프로그래밍 - 2 (0) | 2005.06.29 |
실전 네트웍 프로그래밍 - 1 (0) | 2005.06.29 |