参考:
1、http://community.csdn.net/Expert/topic/3056/3056877.xml?temp=.8741724
2、<<Windows网络编程2>>第8章
3、http://community.csdn.net/Expert/topic/2646/2646592.xml?temp=.9986383
完成端口的定义在参考1、2中已经讲得够详细了,参考1是fzd999 (花差花差)经验的总结,写得详细透彻,是学习完成端口一篇好文章。参考2更不用说了是Windows网络编程的必备。
以前使用完成端口套用的是这两篇文章中都提到的框架。今天放假总结以前学习的东西,发现对完成端口只知其所然不知其所以然,就好像一门武功只知道招式但不理解为何招式这般。静下心来发现参考1,2好像缺少了什么东西。
参考1中提到参考完成端口类似于消息队列(原话为:其实说穿了IOCP不就是一个消息队列嘛!),我觉得这种说法不是很恰当,参考2提到完成端口基于Win32重叠I/O,这重叠I/O又如何解释呢?
参考3中包含了对此的解释——为了避免CPU等待较慢的I/O操作而采用的一种方式,当CPU执行你的代码时遇上一个I/O请求后,系统为你开一根内部线程去处理I/O请求,并且你的线程并不挂起。这好比说把同步的事件做成异步了,对网络编程就是把WSARecv和WSASend变成异步函数了。为了实现同步可以调用MultiObject()和GetOverlappedResult()就可以得到I/O完成的消息,然后再对其作相应的处理。
对完成端口来说,将一个套结字邦定到完成端口后,WSARecv和WSASend会立即返回,提高了系统的效率。可以调用GetQueuedCompletionStatus来判断WSARecv和WSASend是否完成。这样主程序就可以完全等待接受新的连接,线程程序来等待WSARecv和WSASend是否完成了。我想这也是完成端口的真正含义吧。
有了这种观点就可以理解参考2第8章的例子了。主线程接受到一个连接后,调用WSARecv等待该连接发送的数据(不阻塞,由完成端口实现数据的接受完毕判断)。在线程函数中接受完毕,然后用WSASend函数发送给客户数据(同样是不阻塞,直接返回,由完成端口判断数据是否发送完毕)。这样在线程函数中需要区分是发送完毕还是接受完毕。如果是发送完毕,需要调用一个WSARecv函数等待该连接下一次发送数据。