IOCP完成端口

本文详细介绍了Windows平台上的异步IO模型,包括异步调用的工作原理、IOCP(I/OCompletionPort)在连接建立、断开和数据传输中的应用,以及重叠IO(OverlappedI/O)的使用方法和编程示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步IO

Windows上使用的高效异步IO模型。

异步:调用函数后会立刻返回,但当函数返回时,当前IO操作并没有完成,只是投递了一个请求(投递到 IOCP中),IOCP会建立连接(创建一个线程),来通知完成的结果。

  1. 连接的建立:AcceptEx、ConnectEx
  2. 连接的断开:closesocket(同步)、DisconnectEx(异步)
  3. 数据接收:WSARecv
  4. 数据发送:WSASend

img

完成端口

  • 完成:应用程序向系统发起一个 IO 操作,系统会在操作结束后将IO操作完成的结果通知应用程序。
  • 端口:抽象概念,是一种机制。

重叠IO

Overlapped,针对一个socket可以发起多个 IO 操作,无需等待上一个 IO 完成。

(尽管调用 IO 操作是按顺序的,但 IO 操作完成通知是随机的无序的)

img

编程

//创建重叠socket
SOCKET listensock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

bind(...);
listen(...);

//创建IOCP
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
//绑定
CreateIoCompletionPort((HANDLE)listensock, iocp, NULL, 0);

CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads):

  • FileHandle:创建的重叠socket
  • ExistingCompletionPort:创建的iocp
  • CompletionKey:投递请求时作为参数投递到内核,用户层调用GetQueuedCompletionStatus时又会得到CompletionKey,根据该参数可以跟具体的io请求进行关联,判断到底是那一次投递的io请求,重叠结构也是起类似的作用。
  • NumberOfConcurrentThreads:系统允许在完成端口上并发处理IO完成包的最大线程数量。
enum class IO_OP_TYPE{
    IO_ACCEPT,
    IO_SEND,
    IO_RECV,
    IO_CONNECT,
    IO_DISCONNECT
};
//创建重叠结构
typedef struct OverlappedPerIO{
    OVERLAPPED overlapped; //与OverlappedPerIO起始地址是一样的,只要类型转换就可以获取到
    SOCKET socket;
    WSABUF wsaBuf;
    IO_OP_TYPE type;
    char buffer[BUFFER_SIZE];
};

{
    SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
    OverlappedPerIO overlap = new OverlappedPerIO;
    ZeroMemory(overlap, sizeof(OverlappedPerIO);
    overlap->socket = sock;
    overlap->wsaBuf.buf = overlap->buffer;
    overlap->type = IO_OP_TYPE::IO_ACCEPT;

    DWORD dwByteRecv = 0;
    //通常要投递多个请求
    for(;;){
        AcceptEx(listensock, sock, overlap->wsaBuf.buf, 0, 
            sizeof(SOCKADDR_IN) + 16, 
            sizeof(SOCKADDR_IN) + 16,
            &dwByteRecv,
            (LPOVERLAPPED)overlap
            );
    }

    //创建线程,线程函数中调用GetQueuedCompletionStatus函数
    while(true){
        //不断接收完成队列中的完成通知
        GetQueuedCompletionStatus(...);
        switch(overlp->type){
            case IO_ACCEPT:
                setsockopt(...);
                //重新设置overlap的type等
                ...
                CreateIoCompletionPort((HANDLE)listensock, iocp, NULL, 0);
                WSARecv(...);//投递接收消息的请求
            break;
            case IO_RECV:
                //取出读到的数据
                cout << overlap->buffer << endl;
                WSASend(...);//投递发送消息的请求
            break;
        }
    }

    //清理
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值