Asynchronous I/O with TCP/IP
Asynchronous I/O (often referred to as async I/O) allows a program to perform network operations without blocking the calling thread. This improves scalability and responsiveness, especially in UI applications or high‑throughput servers.
Key Concepts
- OVERLAPPED structure – Used to describe asynchronous operations.
- IOCP (I/O Completion Ports) – Efficient mechanism for handling many concurrent I/O requests.
- WSAEventSelect & WSAAsyncSelect – Event‑based notification models.
Basic Pattern
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
void StartAsyncConnect(SOCKET s, const sockaddr_in *addr)
{
OVERLAPPED ol = {0};
ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ConnectEx(s, (sockaddr*)addr, sizeof(*addr), NULL, 0, NULL, &ol) == FALSE)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// handle error
}
}
// Wait for completion (or use IOCP)
WaitForSingleObject(ol.hEvent, INFINITE);
// Check result
DWORD bytes;
GetOverlappedResult((HANDLE)s, &ol, &bytes, FALSE);
CloseHandle(ol.hEvent);
}
Using I/O Completion Ports (IOCP)
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CreateIoCompletionPort((HANDLE)listenSock, iocp, (ULONG_PTR)listenSock, 0);
while (true)
{
SOCKET clientSock = accept(listenSock, NULL, NULL);
CreateIoCompletionPort((HANDLE)clientSock, iocp, (ULONG_PTR)clientSock, 0);
// Prepare a recv operation
WSABUF buf;
char recvBuf[1024];
buf.buf = recvBuf;
buf.len = sizeof(recvBuf);
OVERLAPPED ol = {0};
DWORD flags = 0;
WSARecv(clientSock, &buf, 1, NULL, &flags, &ol, NULL);
}
// Worker thread
DWORD WINAPI Worker(LPVOID lpParam)
{
HANDLE iocp = (HANDLE)lpParam;
DWORD bytes;
ULONG_PTR key;
LPOVERLAPPED ol;
while (GetQueuedCompletionStatus(iocp, &bytes, &key, &ol, INFINITE))
{
SOCKET s = (SOCKET)key;
// Process received data in ol->...
}
return 0;
}
Best Practices
- Prefer IOCP for high‑scale server scenarios.
- Always check
WSAGetLastError()
after an async call. - Free any resources (events, buffers) after completion.
- Use
WSAGetOverlappedResult
for simple cases. - Set socket to non‑blocking mode when mixing sync and async APIs.