C++ の IOCP を使用したソケット通信の実装方法
非同期 I/O を実装する Socket 通信を C++ で実装する手順を以下に示します。
- IOCPオブジェクトを作成します。
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- IOCPオブジェクトにソケットを作成してバインドする:
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, (SOCKADDR*)&addr, sizeof(addr));
CreateIoCompletionPort((HANDLE)sock, hIOCP, (ULONG_PTR)sock, 0);
- WSARecv あるいは WSASend 関数を使ってデータの送受信を行います。
WSABUF wsaBuf;
wsaBuf.buf = // 缓冲区指针
wsaBuf.len = // 缓冲区长度
DWORD bytesTransferred = 0;
DWORD flags = 0;
OVERLAPPED* pOverlapped = nullptr;
WSARecv(sock, &wsaBuf, 1, &bytesTransferred, &flags, pOverlapped, nullptr);
- 完了パケットの受信に1つのスレッドを作成する。
DWORD WINAPI WorkerThread(LPVOID lpParam) {
while (true) {
DWORD bytesTransferred = 0;
ULONG_PTR completionKey = 0;
LPOVERLAPPED lpOverlapped = nullptr;
GetQueuedCompletionStatus(hIOCP, &bytesTransferred, &completionKey, &lpOverlapped, INFINITE);
// 处理接收到的数据
// 重新投递接收请求
WSARecv(sock, &wsaBuf, 1, &bytesTransferred, &flags, pOverlapped, nullptr);
}
return 0;
}
- IOCPの完了パケットを処理するために複数のワーカー・スレッドを作成します:
for (int i = 0; i < numThreads; ++i) {
HANDLE hThread = CreateThread(NULL, 0, WorkerThread, NULL, 0, NULL);
CloseHandle(hThread);
}
以上のステップで、IOCPを使ってSocket通信を行うことができます。例はあくまで基本的なもので、実際の利用では必要に応じて調整や拡張が必要になることにご注意ください。