MSDN Documentation

TCP/IP Home

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

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

Further Reading