本文作者: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 是否效率更高一些,没有必要自己再增加其他种类的线程.
|