IOCP完成端口

异步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;
        }
    }

    //清理
}

相关推荐

  1. iocp简单例子

    2024-03-21 13:22:02       52 阅读
  2. Spring IOC

    2024-03-21 13:22:02       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-21 13:22:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-21 13:22:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-03-21 13:22:02       82 阅读
  4. Python语言-面向对象

    2024-03-21 13:22:02       91 阅读

热门阅读

  1. 力扣126双周赛

    2024-03-21 13:22:02       45 阅读
  2. electron-builder打包

    2024-03-21 13:22:02       46 阅读
  3. 物理设计概念 -- 物理层次结构

    2024-03-21 13:22:02       34 阅读
  4. [Open3d]: 知识记录

    2024-03-21 13:22:02       40 阅读
  5. mybatis---->tx中weekend类

    2024-03-21 13:22:02       43 阅读
  6. Mac传文件到云服务器

    2024-03-21 13:22:02       45 阅读
  7. 二叉树遍历144、94、145

    2024-03-21 13:22:02       41 阅读
  8. Python基础算法解析:决策树

    2024-03-21 13:22:02       37 阅读
  9. css第一个元素first-child匹配失败原因

    2024-03-21 13:22:02       38 阅读
  10. 后端使用前端页面的很好的推荐Layui

    2024-03-21 13:22:02       38 阅读
  11. mysql 学习

    2024-03-21 13:22:02       33 阅读
  12. 初学者指南 | PostgreSQL中的加密机制如何运作?

    2024-03-21 13:22:02       41 阅读