本文作者: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底层通信模型的架构设计以及一个通用的高性能服务器模型架构,希望能与各位同仁共同研究高性能服务器研发问题。