首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  网络/通讯  |  高性能网络服务器


完成端口的深入理解及一种变态用法


原作者:sodme    源出处:CSDN    发布者:施昌权    发布类型:转载    发布日期:2009-02-23

      

   本文作者:sodme
   本文出处:http://blog.csdn.net/sodme
   声明:本文可不经作者同意,任意被转载、引用、复制,但任何对本文的引用都必须注明本文作者,出处以及本行声明信息。谢谢。

   作为WIN平台下同时管理数千个连接的最为高效的网络模型,完成端口已经被越来越多的人认识和熟悉。通常情况下,一种经典的完成端口使用模式是:
   (1)创建完成端口,并在指定端口开始监听;
   (2)创建接受连接线程,用accept或acceptEx接受客户端连接;
   (3)创建工作者线程,处理客户端的数据收发。
  
   众所周知,CreateIoCompletionPort函数,有两个作用,一是“创建”一个完成端口,二是将一个socket与已经创建的完成端口句柄相“绑定”,绑定之后,基于该socket的收、发、断开等事件都可以被完成端口感知。一般情况下,较为正常的思维状态下,CreateIoCompletionPort的绑定是选在accept函数执行以后或acceptEx函数完成之时与套接字相绑定。但是,这并不说明CreateIoCompletionPort函数就不能进行其它形式的绑定。

   事实上,CreateIoCompletionPort关心的只是一个套接字,它并不关心这个套接字到底是通过accept而来的,还是用来connect的。也就是说,它并不关心当前的这个socket是用于接受客户端连接的,还是用来连接其它服务器的。那就是说,CreateIoCompletionPort函数,也可以用来绑定一个连接到其它服务器的客户端socket。

   这个问题的提出,是我在设计网关服务器时。

   网关服务器,承担的主要工作就是两个:向内,负责客户端数据包的分发;向外,负责把内部服务器所有的返回数据包统一通过网关发送出去。网关服务器上,我创建了两个IOCP,一个用来向外接受玩家与网关的数据交换,另一个用来与内部的服务器进行数据转发。由于本人较懒,所以想在内部的那个服务器上,也采用IOCP模型来作。

   在网关上负责向内部服务器提供数据转发的这个IOCP,必须要能正确识别哪一个内部服务器使用的是哪一个套接字。这样,内部服务器与网关服务器之间的套接字确认就有两种方式。一种方式,是由内部服务器连接到网关服务器上,随后向网关服务器发送一个注册包,告诉网关服务器当前的这个socket是哪个内部服务器;另一种方式,是由网关服务器先创建若干个指定的socket,然后用这些socket去连接指定类型的内部服务器。前面,我已经说过,IOCP可以绑定的套接字,不仅是可以被accept来的套接字,也可以是connect其它服务器的套接字。所以,我选用了后一种方式。这样在网关服务器对内的IOCP的逻辑处理上,就少了一项判定和一个包的逻辑解析。当网关流量非常巨大时,每节省一项判定或一种分支,效率和资源都会得到更有效的利用,高性能从哪里来?就是从这样的一点一滴的改进中来。到目前为止,我能测试到的网关服务器流量上限是每秒10M到12M,据说,局域网的某些HUB给每台机子的带宽只分了10M左右的出口带宽,所以,我无法确定如果把局域网的交换机换成电信级的,数据交换量会不会有一个更大的提高,不久,公司会进一个这样的电信级交换机,到时可以作进一步的测试。

   过段时间,我会在我的BLOG(http://blog.csdn.net/sodme)上公布我的IOCP底层通信模型的架构设计以及一个通用的高性能服务器模型架构,希望能与各位同仁共同研究高性能服务器研发问题。


   评论

#webspider 发表于2005-07-13 17:46:00  IP: 61.186.252.*
sodme:我有个问题请教一个问题:我在写一个服务器程序,问题是这样的
我在服务器中创建一个iocp
服务器中的一个session的对应着一个connection,和这个iocp 邦定在一起,可是session还需要对文件系统操作,
读写文件,我想把对文件操作的io handle 和这个iocp 邦定在一起,这样的话,
当 GetQueuedCompletionStatus 返回时,我如何知道一个文件io handle 还是网络io socket?
#sodme 发表于2005-07-14 09:22:00  IP: 61.186.252.*
to webspider:
CSDN的blog对于15天之前的文章采取cache方式处理,回贴不会马上显示在文章后。

你所说的问题,我基本明白是怎么回事了。但我建议你不要在get函数里去作文件I/O操作,这将相当影响效率。你可以将收到的包统一放入接收的数据队列中,使用另外的写入线程将此队列的所有数据一个个写入文件。
#webspider 发表于2005-07-18 17:48:00  IP: 61.186.252.*
谢谢! sodme
如果我现在要从文件系统中读数据的话,由于从文件系统要读的数据比较多,因为我不知道文件io什么时候完成,在这种情况下用iocp可以吗,如何不用它的话,使用同步技术的话,是否效率太低阿?
#sodme 发表于2005-07-18 20:23:00  IP: 61.186.252.*
to webspider:
上次没有看完全你的问题。你是想让完成端口即作文件读取又作网络读取是吧?如果你坚持使用重叠IO进行文件操作的话,可不可以考虑create两个完成端口对象,一个专门负责作网络IO,另一个专门负责作文件IO,这样你可以互不干扰。在网络IO的接收事件中,你直接把接收到的数据放到数据队列中,用另外的线程来将此数据队列的数据一个个通过重叠IO再写入文件。读文件是相反。但是,我认为这样似乎没必要,文件IO模块由另外的线程去作读、写,而不作成重叠IO的形式呢?你可以对比一下两种作法的效率。
#webspider 发表于2005-07-28 10:16:00  IP: 61.186.252.*
to sodme:

另一个问题,我要是把所有的执行逻辑都放在workerthread 可以吗?我是这样想的
IOCP 提供了很好的线程管理机制,如果没有这一点,哪他也跟其他的异步机制没有区别
.所以我想要是把所有的线程管理工作都交给IOCP 是否效率更高一些,没有必要自己再增加其他种类的线程.


关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号