IOCP 的前身 : 纯重叠io服务器模型
前提:
IOCP的整体编程模型跟上面的纯重叠io 非常类似. 纯重叠io使用OVERLAPPED + APC函数完成.
这种模型的缺点是必须让调用apc函数进入alterable状态. 而IOCP解决了这个问题.IOCP让我们自己创建一些线程,
然后调用GetQueuedCompletionStatus 来告诉我们某个io操作完成, 就像是在另一个线程中执行了APC函数一样;
使用IOCP 的时候,一般情况下需要自己创建额外的线程,用于等待结果完成(GetQueuedCompletionStatus)
使用到的函数:
CreateIoCompletionPort : 创建/ 关联一个完成端口 .
第3个参数是一个自定义数据, 第4个是最多N个线程可被调用;
注意与其关联的HANDLE 必须要有OVERLAPPED属性的
//创建一个完成端口
HANDLE hComp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)
//关联到完成端口. 第3个参数是一个自定义数据
//在GetQueuedCompletionStatus将携带这些数据返回. 这个自定义数据将一直与此套接字绑定在了一起
CreateIoCompletionPort((HANDLE)client_socket, hComp, (DWORD)pSockData, 0);
GetQueuedCompletionStatus :
1. 将调用线程投入睡眠, 等待直到 IOCP 完成时被唤醒;
2.一旦类似WSARecv / WSASend 完成后 . 用此函数获取结果,就想APC函数一样,一旦完成io操作就调用. 此函数一般情况都在某一个线程中使用.注意一旦在某个线程中调用了此函数,这意味着,
该线程就像被指派给了IOCP一样,供IOCP使用. 总之这个行为就想APC函数在另一个线程被调用了;
关于解除关联: 一旦一个套接字关闭了 , closehandle /closesocket. 就将从IOCP的设备句柄列表中解除关联了
关于线程:
CreateIoCompletionPort 最后一个参数用于指定IOCP最多执行N个线程(如果是0 则使用默认CPU的核数). 但一般情况下,我会预留一些额外的线程.比如
我的CPU是4核即IOCP最多可使用 4个线程 , 不过一般情况下会创建 8 个线程,给IOCP预留 额外4个线程 . 原因是如果IOCP
有5个任务已经完成, 最多只有4个线程被唤醒. 如果其中某个线程调用了WaitForSingleOb