以前写过一篇用python封装IOCP的文章,这几天因朋友需要,再一次封装了iocp接口。这一次我并不是简单的把原有代码拿过来简单的修修改改,基本上是推到重来。改正第一次封装时的许多缺点,同时修正了许多bug,再回首看以前的代码,感觉自己在进步。这次封装iocp,收获了以下几点知识:
1. 数据的重复投递。一般情况下,一个Socket句柄在同一时刻最多只能有一次WSASend与SWARecv,如果多次投递WSASend或者WSARecv,有可能造成数据的重复发送或重复接收。我一般为每个Socket创建两个buffer,一个用于发送数据(send buffer),别一个用于接收数据(recv buffer),当send buffer中有数据的时候,就投递WSASend,如果send buffer为空,则不投递,且保证任何时刻该Socket只有一次WSASend投递。同样,当recv buffer满的时候,不投递WSARecv,如果recv buffer有空闲空间,就投递WSARecv投,且保证同一时刻该Socket只有一次WSARecv递。
2. 如果WSARecv或WSASend投递失败,将不会接收到通知。如:if (WSARecv(sock, …) == SOCKET_ERROR && err_no != WSA_IO_PENDING) { // 投递失败,不会为这次投递发送通知。 }
3. 关于连接断开时接收到的通知。如果iocp检测到Socket连接已经断开,程序马上会收得到通知,而且有时候会收到不至一次通知,这取决于你在该socket上投递WSASend与WSARecv的次数。例如你在一个socket上投递了一次WSASend与一次WSARecv,在这两次投递还没有被完成时,如果socket断开了连接,那么GetQueuedCompletionStatus()将会收到两次通知。一般情况下,我们会为每个连接准备两个重叠IO结构(Overlapped struct),一个用于接收数据,另一个用于发送数据。当连接断开的时候,就应该正确地释放这些资源。
4. 对于Socket的管理。一般情况下,使用字典或者列表来管理所有的连接。以字典为例,当连接创建的时候,将连接加入到字典中,而连接断开的时候,将连接从字典中移除。因为IOCP可能有多个工作者线程,所以在执行上述操作时,应该保证操作的原子性,也就是多线程同步问题。例如:一个工作者线程正在对一个连接投递WSASend操作,而同时另一个工作者线程检测到这个连接已经断开,并将该连接从字典中移除,并释放了与该连接相关的资源,此时就会出现不可预知的情况。
5. 关于IOCP的性能。网上有一些文章说IOCP能同时处理上万个连接,但我写的IOCP程序根本无法达到这个数,于是对IOCP的性能进行了怀疑。其实,经过我的调试发现,IOCP的效率确实高,处理上万个连接应该没问题,至于为什么自己的程序没有能达到这个数量级,我觉得主要是我的程序要维护成百上千个连接的缘故。我用hash_map来管理所有的连接,在程序中经常要根据key来获取相应的数据结构,如果很频繁的调用这样的操作,是会引起性能问题的。可以写一个简单的C++程序来感受一下:
// 下面这段代码在VC下是很占资源的
map<int, int> dict;
for (int i = 0; i < 1000; ++i)
dict[i] = i;
while (1) {
for (int i = 0; i < 1000; ++i) {
dict[i];
}
Sleep(10);
}
上面这些内容是我第二次封装iocp所尝到的东西,网上还有许多关于iocp的好文章可供参考。如果您需要iocp的python封装版本,请留下您的邮箱,也欢迎与我交流。
分享到:
相关推荐
基于ACE的IOCP封装,只要继承iocp_server 类就可以实自己的服务器了。 wonderful.
iocp异步通信封装,适合中小型并发服务器框架,性能经测试还可以
windows iocp网络通讯库封装
由于兼容问题,不再使用Lib形式的封装,使用DLL 去掉0缓冲,接收数据大小有限制 IOCP只负责接收前256字节,剩下的根据自定义协议(肯定知道包的大小)再recv 添加Connect函数,所以此IOCP不仅可以作为服务端,同时也可以作为...
经典的iocp 封装类, 放在这里以后应该能用上。很简单易懂的。
我们的一个项目的服务器端通信层,IOCP类是在此基础上写的,使用了近半年,并发量不大,1k上下,(不过曾做过压力测试,10k的并发量没有问题)还算比较稳定,基本上满足需求。
IOCP_V5.rar(20110208) 服务端: 取消监听线程,采用AcceptEx异步接收套接字,效率更高 支持大量并发连接不丢包 压力测试后尚未发现内存泄露 IOCP_V4.rar(20110208) 服务端: 代码更加稳定,取消监听线程的异常处理 删减...
决定写一个IOCP,封装的很好的,这是一个库,请在VC2010下编译。 客户端和服务器都适用,但是只完成了TCP的部分,没有完成UDP的部分。 面向对象的方式编写。 包含连接器,内存管理,等模块。 无协议模块
网上一个朋友的IOCP类,我现在在研究IOCP,但是发现这个类有些缺陷,但是不知道如何修改一遍提高性能,还有就是我做压力测试,发现这个类有内存泄露,总是以4K的大小在增长,希望懂IOCP的朋友帮忙看看~~
一个老外写的IOCP的dll。对于不会完成端口编程的人只需要进行加载DLL,和调用接口函数就能完成服务器编程。很难找的代码哦。资源里面有文档和例子程序
A simple application using IO Completion Ports and WinSock。老外写的IOCP封装类,使用了线程池和内存池。很不错的东西.资源里面有文档和例子程序
封装了IOCP逻辑,条理清晰,包含例子.
iocp-epoll的几个例子,提供参考。 其中,iocp包含了几种使用方式,同步异步处理方式, epoll为linux下面使用,编译时可以使用下面简单命令, g++ -p -g -o hhh ***.cpp -l pthread
一个VC++6.0 封装的IOCP类,有丰富的注释,能较快的借鉴和使用。
经过封装的IOCP完成端口模型客户端。 主要功能有发送普通文本数据,传输文件,下载文件
使用IOCP完成端口和SOCKET封装的异步TCP类。 支持客户端和服务器的常用TCP接口:绑定Bind、监听Listen、接收Recv、连接Conn、发送Send、关闭Close。所有接口均使用异步回调的方式处理,内部实现使用Windows下性能...
iocp完成端口的封装,使用TCP的IOCP实现,可以传送大消息包、文件,同一客户端可以同时发送多个文件 // 1、用TClients创建一个对象,pClients // 2、调用pClients->CreateClient(...)函数,参数1、2是要连接的服务端...
采用IOCP模型简单封装的网络通信模型,可以用来学习交流使用。代码里面有些是根据个人业务修改的部分,也可以自己修改成所需,还有一些功能没有完善,不过可以使用。
源码使用了高级的完成端口(IOCP)技术,该技术可以有效地服务于多客户端。代码封装了IOCP并提供了一个简单的echo版本的可以传输文件的客户端/服务器程序
把Winsock IOCP完成端口模型封装成c++类.zip