利用APC异步模型实现底层socket高效并发易语言源码前言:
socket有着不同的模型,不同的模型有不同的并发性能。
常用的模型一般有线程池模型,Select模型,Asynchronous异步模型,IOCP等等(WSAAsyncSelect内部即使用IOCP),不同的模型有不同的优势。
本程序使用的模型利用Asyncroneus Procedure Call完整实现。本质上仍然是Asynchronous异步模型,但是和原来的Asynchronous异步模型不同的是,本程序直接实现了WSPSelect的IOCTL_AFD_SELECT异步过程,和其他的异步过程的实现函数完全不同(注意:WSASelect并未开放异步接口,程序参考ReactOS实现)
叫“全网首发”可能也有点问题,不知道之前有没有大佬逆向过winsock实现过相似的异步过程。(不过我反正翻不到,翻到了可以提醒我)
正文:
原系统的WSASelect并未开放异步接口,但是实际上,WSASelect调用NtDeviceIoControlFile实现,NtDeviceIoControlFile函数本身可以实现APCRoutine,于是便有了这个程序。
在代码中,WSPSockProcessAsyncSelect(我乱取的名字,别太在意)实现了Select过程的异步化。本命令被调用后将会直接返回,不会阻塞程序,当select过程产生真实的数据反馈时,内核将会异步调用ApcRoutine:
所以只要稍加封装便可得到这个异步模型,这个异步模型可以实现socket消息的异步通知(包括客户连接,send消息,recv消息等等)
提示:IOCP模型实际工作原理与此类似,不过IOCP模型是使用完成端口实现的异步调用。
程序效率对比(仅仅比较多客户accept和断开的速度,测试结果已经去除包括输出、数据显示在内的可能干扰程序速度的因素):
BBTCP纯连接效率(IOCP实现):
MSAFD纯连接效率(即本程序):
可以看到效率十分接近,证明本模型在1000用户量依次连接时异步效率不错。(在测试1000连接时,BBTCP出现了大约1%的连接没有连上,本程序在此测试中未出现此情况。在测试10000连接时,本程序也出现了约1%的连接没有连上的情况,这也说明本单线程模型可能不是很适合超大量用户并发)
已知问题:
AsyncSelect不会记录事件是否已经发生过!即如果一个客户向本模型请求了Client,模型如果没有accept的话,异步接口将会被一直触发(AFD_EVENT_ACCEPT事件)!直到accpet为止!
同理,如果程序向服务端send了数据,服务端没有recv,异步接口将会被一直触发(AFD_EVENT_RECEIVE事件)。
这个问题其实和select本身有关,select其实就是查询是否存在某事件,如果事件没有响应的动作(例如还有数据没有recv),该事件将会一直被查询到,直到事件被响应。

发表回复

后才能评论