再探完成端口[亲测有效]

再探完成端口[亲测有效] 一 快速入门      有关完成端口的概念,以及相关的一些API就不讨论了,因为网上介绍这些东西的文章太多了。这里关注的是如何组织代码。首先我们来看《WINDOWS网络编程技术》第八章中有关完成端口的例子。代码可以在网上找到,这里就不贴了。这个不到300行的程序可以让我们迅速入门。 查看程序,我们可以看到使用完成端口的服务器的一般步骤:1.        创建一个完成端口

大家好,欢迎来到IT知识分享网。 


 
快速入门
       有关完成端口的概念,以及相关的一些API就不讨论了,因为网上介绍这些东西的文章太多了。这里关注的是如何组织代码。首先我们来看《WINDOWS网络编程技术》第八章中有关完成端口的例子。代码可以在网上找到,这里就不贴了。这个不到300行的程序可以让我们迅速入门。
 
查看程序,我们可以看到使用完成端口的服务器的一般步骤:
1.
         创建一个完成端口。第四个参数保持为0,指定在完成端口上,每个处理器一次只允许执行一个工作者线程。
2.
         判断系统内到底安装了多少个处理器。
3.
         创建工作者线程,根据步骤2 )得到的处理器信息,在完成端口上,为已完成的I / O请求提供服务。在这个简单的例子中,我们为每个处理器都只创建两个工作者线程。
4.
         准备好一个监听套接字,在端口5150上监听进入的连接请求。
5.        
使用
accept
函数,接受进入的连接请求。
6.        
创建一个数据结构,这个数据结构通常称之为完成键,同时在结构中存入接受的套接字句柄,以及其他在处理
Socket IO
时需要的信息,以备后用
7.        
调用
CreateIoCompletionPort
,将自
accept
返回的新套接字句柄同完成端口关联到一起。通过完成键(
CompletionKey
)参数,将
6
中的数据结构传递给
CreateIoCompletionPort
8.        
开始在已接受的连接上进行
I/O
操作。在此,我们希望通过重叠
I/O
机制,在新建的套接字上投递一个或多个异步
WSARecv

WSASend
请求。这些
I/O
请求完成后,一个工作者线程会为
I/O
请求提供服务,同时继续处理未来的
I/O
请求,稍后便会在步骤
3 )
指定的工作者例程中,体验到这一点。
9.
         重复步骤5 ) ~ 8 ),直至服务器中止。
 
对于程序的分析
很明显,5-8步是关键。而在工作者线程中,如何处理IO请求也是关键。其中有两个数据结构很重要,一个就是完成键结构,另一个就是重叠IO结构。这两个结构都是指针的指针,这种晦涩的设计是为了使结构具有更好的扩展性。个人觉得理解怎么使用这两个结构就理解了完成端口编码的核心。当然,要学习操作完成端口的实现机制还是需要了解windows内核是如何维护完成队列之类更深层的东西,这些内容不在本文讨论范围之内。
 
我们可以把完成键结构看作是服务主线程accept连接时和工作者线程交互的平台。一般我们在客户端连接时会将客户端Socket句柄放入这个结构中。除此以外,所有在一次Socket IO中无法保存的数据结构都可以扔到该结构中,让它可以在多次Socket IO中重复使用。例如客户端要向服务器传文件,那么可以在完成键中添加服务器上打开的文件句柄,每次Socket IO就可以使用这个句柄读写数据。
 
我们可以把重叠IO看作是一个可以扩展的Buffer类型。这个Buffer可以根据具体的需求进行改变,它可以携带写入、写入完成、写出、写出完成的标志,也可以携带具体接受或发送的数据,等等。
 
在实际应用中,我们可以将以上两个结构设计成CompletionKey和Buffer两个类,但是要保证代表重叠IO的Buffer类指向的数据结构头部就是一个重叠结构。
 
解决了这两个结构的问题之后还有另一个问题,就是如何进行工作者线程的编程。完成端口的特点是一次数据收到之后程序会得到通知。那么怎么判断我收到的数据是完整的,可以进行下一步处理的呢?通常我们会根据已收到的数据流特征来判断它是否是完整的,对于完整的数据我们就可以进行下一步处理,而对于不完整的数据我们需要等待下次的数据,并且把它和以前的数据拼接起来。这就需要我们实现一个高效的Buffer结构来满足这些需求。当然,这些功能在Windows网络编程技术一书中给出的例子并没有实现。
 
 

 
实例分析
 
       经同事指点,我在CodeProject上找到了一个比较符合实际需求的完成端口的例子。它提供了三种类型的服务器,一是简单的EchoServer,另一个是基于自定义包结构的服务器,还有一个就是基于命令的服务器。这三个服务器只是在处理数据的逻辑上有些差异,整体架构都是一样的。
 
基于包结构的服务器和基于命令的服务器的优劣
在游戏服务器中,我们一般有自己的协议,这个协议可以基于包结构,也可以基于命令结构,可以根据需要灵活选择。通常认为包结构设计的好的话服务器和客户端只需要一个连接,而基于命令的服务器如果需要传数据,那么最好使用另一个连接,否则将会无法判断收到的是数据还是命令。但是无论使用哪一种,一个好的解析器是必要的。它可以帮助你高效地解析包内容或者是命令内容。
 
服务器的组织结构
       服务器的主体部分是一个类库工程,main函数所在工程只是继承与类库工程中的CSocketServer类来实现一些逻辑。类库工程对一些windows内核对象进行了包装,例如事件,线程等等。比较重要的部分就是CSocketServer类,Socket类,以及CIOBuffer类的实现。CSocketServer类的协作图如下:

 再探完成端口[亲测有效]

 

to be continued..

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/24602.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信