SocketProgram - IOCP Program

至此整个IOCP的基础知识算是介绍完了,作为总结,可以回顾下几个关键步骤:

1、 用CreateIoCompletionPort创建完成端口;

2、 定义IOCP线程池函数,类似消息循环那样写一个“死循环”调用GetQueuedCompletionStatus函数,并编写处理代码;

3、 创建线程;

4、 将重叠IO方式的对象句柄绑定到IOCP上。

只要记住了上面4个关键步骤,那么使用IOCP就基本掌握了。最后作为补充,让我再来讨论下这个核心步骤之外的一些附带的步骤。

现在假设我们已经创建了一个这样的IOCP线程池,而且这个线程池也工作的非常好了,那么我们该如何与这个线程池中的线程进行交互呢?还有就是我们如何让这个线程池停下来?

其实这个问题可以很简单的来思考,既然IOCP线程池核心的线程函数中有一个类似消息循环的结构,那么是不是也有一个类似PostMessage之类的函数来向其发送消息,从而实现与IOCP线程的交互呢?答案是肯定的,这个函数就是PostQueuedCompletionStatus,现在看到它的名字,你应该已经猜到它的用途了吧?对了,它就是用来向这个类似消息循环的循环中发送自定义的“消息”的,当然,它不是真正的消息,而是一个模拟的“完成状态”。这个函数的原型如下:

BOOL WINAPI PostQueuedCompletionStatus(

__in          HANDLE CompletionPort,

__in          DWORD dwNumberOfBytesTransferred,

__in          ULONG_PTR dwCompletionKey,

__in          LPOVERLAPPED lpOverlapped

);

它的参数与GetQueuedCompletionStatus类似,其实为了理解上的简单,我们可以认为PostQueuedCompletionStatus的参数就是原样的被copy到了GetQueuedCompletionStatus,怎么调用这个函数就应该可以理解了。通常在需要停止整个IOCP线程池工作时,就可以调用这个函数发送一个特殊的标志,比如设定dwCompletionKey为NULL,并且在自定义lpOverlapped指针结构之后带上一个表示关闭的标志等。这样在线程函数中就可以通过判定这些条件而明确的知道当前线程池需要关闭。当然也可以定义其它的操作扩展码来指定IOCP线程池执行指定的操作。下面的例子代码演示了如何发送一个IO完成状态:

MYOVERLAPPED *pOL = new MYOVERLAPPED ;

.......//其它初始化代码

pOL->m_iOpCode = OP_CLOSE;//指定关闭操作码

.......

PostQueuedCompletionStatus(hICP,0,NULL,(LPOVERLAPPED)pOL);

至此IOCP的基础性的支持算是介绍完了,本篇文章的主要目的是为了让大家理解IOCP的本质和工作原理,为轻松驾驭IOCP这个编程模型打下坚实的基础。最终需要掌握的就是认识到IOCP其实就是一个管理IO操作的自定义线程池这一本质。实际编码时决策性的问题就是理解最大并发数和预创建线程数的意义,并根据实际情况设定一个合理的值。


你可能感兴趣的:(SocketProgram - IOCP Program)