说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

boost在windows平台下自带超强 IOCP 的ASIO

HTML文档下载 WORD文档下载 PDF文档下载
在win32平台上,asio是基于IOCP技术实现的,我以前也用过IOCP,却没想到居然能扩展成这样,真是神奇!

boost基本上啥都有,用不着用某人写的不完整的,缺陷的代码。

  ASIO攻破

  花了足足3天时间,外加1天心情休整,终于在第5天编写出了一个能运行的基于asio和thread_group的框架,差点没气晕过去,把源码都看懂了才感觉会用了。
测试了一下,debug下一万次回应耗时800+毫秒,release下是200+毫秒,机器配置双核2.5G英特尔,4个线程并行工作,无错的感觉真好,再也不用担心iocp出一些奇怪的问题啦,因为是巨人们写的实现,呵呵。

  进入正题,简要说一下asio的实现原理吧。在win32平台上,asio是基于IOCP技术实现的,我以前也用过IOCP,却没想到居然能扩展成这样,真是神奇!在其他平台下还会有别的方法去实现,具体见io_service类下面这部分的源码:

 

// The type of the platform-specific implementation.#if defined(BOOST_ASIO_HAS_IOCP)   typedef detail::win_iocp_io_service impl_type;   friend class detail::win_iocp_overlapped_ptr;#elif defined(BOOST_ASIO_HAS_EPOLL)   typedef detail::task_io_service<detail::epoll_reactor<false>> impl_type;#elif defined(BOOST_ASIO_HAS_KQUEUE)   typedef detail::task_io_service<detail::kqueue_reactor<false>> impl_type;#elif defined(BOOST_ASIO_HAS_DEV_POLL)   typedef detail::task_io_service<detail::dev_poll_reactor<false>> impl_type;#else   typedef detail::task_io_service<detail::select_reactor<false>> impl_type;#endif

这部分代码其实就在boost::asio::io_service类声明中的最前面几行,可以看见在不同平台下,io_service类的实现将会不同。很显然,windows平台下当然是win_iocp_io_service类为实现了(不过我一开始还以为win_iocp_io_service是直接拿出来用的呢,还在疑惑这样怎么有移植性呢?官方文档也对该类只字不提,其实我卡壳就是卡在这里了,差点就直接用这个类了^_^!)。

  那么就分析一下win_iocp_io_service的代码吧,这里完全是用IOCP来路由各种任务,大家使用post来委托任务,内部调用的其实是IOCP的PostQueuedCompletionStatus函数,然后线程们用run来接受任务,内部其实是阻塞在IOCP的GetQueuedCompletionStatus函数上,一旦有了任务就立即返回,执行完后再一个循环,继续阻塞在这里等待下一个任务的到来,这种设计思想堪称神奇,对线程、服务以及任务完全解耦,灵活度达到了如此高度,不愧为boost库的东西!我只能有拜的份了...


  说一下总体的设计思想,其实io_service就像是劳工中介所,而一个线程就是一个劳工,而调用post的模块相当于富人们,他们去中介所委托任务,而劳工们就听候中介所的调遣去执行这些任务,任务的内容就写在富人们给你的handler上,也就是函数指针,指针指向具体实现就是任务的实质内容。其实在整个过程中,富人们都不知道是哪个劳工帮他们做的工作,只知道是中介所负责完成这些就可以了。这使得逻辑上的耦合降到了最低。不过这样的比喻也有个不恰当的地方,如果硬要这样比喻的话,我只能说:其实劳工里面也有很多富人的^o^! 。很多劳工在完成任务的过程中自己也托给中介所一些任务,然后这些任务很可能还是自己去完成。这也难怪,运行代码的总是这些线程,那么调用post的肯定也会有这些线程了,不过不管怎么说,如此循环往复可以解决问题就行,比喻不见得就得恰当,任何事物之间都不可能完全相同,只要能阐述思想就行。


  最后还要说明的一点就是:委托的任务其实可以设定执行的时间的,很不错的设定,内部实现则是通过定时器原理,GetQueuedCompletionStatus有一个等待时间的参数似乎被用在这方面,还有源码中的定时器线程我并没有过多的去理解,总之大体原理已基本掌握,剩下的就是使劲的用它了!!!


  另外为了方便人交流,在这里插入一些代码可能更容易让人理解吧,
  下面这个是启动服务时的代码:

 

void ServerFramework::run(){     boost::thread_group workers;    for (uint32 i = 0; i < mWorkerCount; ++i)         workers.create_thread(             boost::bind(&boost::asio::io_service::run, &mIoService));     workers.join_all();}

在打开前就得分配好任务,否则线程们运行起来就退出了,阻塞不住,任务的分配就交给open函数了,它是分配了监听端口的任务,一旦有了连接就会抛出一个任务,其中一个线程就会开始行动啦。

 

void ServerFramework::open(const String& address, const String& port, uint32 nWorkers /**//*= DEFAULT_WORKER_COUNT*/){    // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).     boost::asio::ip::tcp::resolver resolver(mIoService);     boost::asio::ip::tcp::resolver::query query(address, port);     boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);      mAcceptor.open(endpoint.protocol());     mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));     mAcceptor.bind(endpoint);     mAcceptor.listen();      mNextConnection = new Connection(this);     mAcceptor.async_accept(mNextConnection->getSocket(),         boost::bind(&ServerFramework::__onConnect, this,         boost::asio::placeholders::error));      mWorkerCount = nWorkers;    if (mWorkerCount == DEFAULT_WORKER_COUNT)    {         mWorkerCount = 4;     }}

open函数中给io_service的一个任务就是在有链接访问服务器端口的情况下执行ServerFramework::__onConnect函数,有一点需要格外注意的,io_service必须时刻都有任务存在,否则线程io_service::run函数将返回,于是线程都会结束并销毁,程序将退出,所以,你必须保证无论何时都有任务存在,这样线程们即使空闲了也还是会继续等待,不会销毁。所以,我在ServerFramework::__onConnect函数中又一次给了io_service相同的任务,即:继续监听端口,有链接了还是调用ServerFramework::__onConnect函数。如果你在ServerFramework::__onConnect执行完了还没有给io_service任务的话,那么一切都晚了...... 代码如下:

 

void ServerFramework::__onConnect(const BoostSysErr& e){    if (e)    {         MOELOG_DETAIL_WARN(e.message().c_str());     }      Connection* p = mNextConnection;     mNextConnection = new Connection(this);     // 再次进入监听状态     mAcceptor.async_accept(mNextConnection->getSocket(),         boost::bind(&ServerFramework::__onConnect, this,         boost::asio::placeholders::error));     // 处理当前链接     __addConnection(p);     p->start();}

最后,展示一下这个类的所有成员变量吧:

 

 // 用于线程池异步处理的核心对象    boost::asio::io_service mIoService;    // 网络链接的接收器,用于接收请求进入的链接    boost::asio::ip::tcp::acceptor mAcceptor;    // 指向下一个将要被使用的链接对象    Connection* mNextConnection;    // 存储服务器链接对象的容器    ConnectionSet mConnections;    //// 为链接对象容器准备的strand,防止并行调用mConnections    //boost::asio::io_service::strand mStrand_mConnections;    // 为链接对象容器准备的同步锁,防止并行调用mConnections    boost::mutex mMutex4ConnSet;    // 为控制台输出流准备的strand,防止并行调用std::cout    AsioService::strand mStrand_ConsoleIostream;    // 工作线程的数量    uint32 mWorkerCount;

但愿这篇随笔也能对正在研究asio的朋友们有所帮助吧。

转载自:http://www.cppblog.com/shanoa/archive/2009/06/26/88606.aspx

 

 

 

 

 

VB5.0中基于桌面的屏幕技巧 VB5.0中实现字体闪烁效果 VB5实现窗口图像缩放、滚动技巧 VB6.0动态加载ActiveX控件漫谈 VB编程步步高-表单篇 VB编程常见问题 VB编程中如何锁定鼠标 VB创建位图菜单 VB实现按钮浮动效果 VB应用程序中的工具提示和状态显示 VB中处理长列表框项的两种方法 VB中多级下拉列表的实现 VB中防止将重复项目添加到列表框控件中 VB中实现菜单分割 VB中实现带预览的对话框 VB中实现同一窗口的多个实例及控件的动态增减 VB中阴影字体的实现 VB自定义数据结构的传输转换 Visual Basic 窗体背景花纹的实现 Visual Basic 中的界面设计原则和编程技巧 Visual Basic 中文本框处理技巧集萃 Visual Basic 中字符淡出淡入的实现 Visual Basic窗体背景花纹的实现 Visual Basic下工具条的制作 Visual Basic中的界面设计原则和编程技巧 Visual Basic中在同一界面输入大量数据的几种方法 VisualBasic中的界面设计原则和编程技巧 VisualBasic中用户界面的设计原则 把 VB 标准的工具栏变成平面式 把窗体卸载干净-VB资料 保持初始的窗体大小-VB资料 我为什么在2000svr下,安装realserver7.0,装不上??? 如何传递消息 请问如何把 一个数组的值放到表格的某一行中 请教,如何使对话框的模板在程序启动后变大 怎样将在一个网页中的值传递给另一网页用?!急 用xsl解析<iframe>出现问题! 救命,在win2k下使用IIS+php4,无援无辜启动了好多php.exe进程。 关于多语种开发的问题 在MFC中出现libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main错误的可能有几种,如何解决? 有没有对音箱价格了解的,也许你懂一点就能回答我的问题。 求助:如何设置Jet OLEDB:Database Password的属性 .mdb数据库的字符型字段不能超过50个字符,但是我要存入更长的字符于一个字段该怎么办呢? 我只安装了Rose,Vss,却常有提示:虚拟内存不足,我在“设置”中改为499mb,还是没用 HtmlInputFile的缺陷,还可以用什么控件或方法来做? 问一下wdl格式的文件用什么软件可以打开? 先来的得分。OVERRIDE 和 OVERLOAD 的区别究竟是什么?谢谢! ip地址的添加, 大家看看什么原因出错???SOS 又是一个巨简单的问题,怎么偶老是问这样的问题? 为何会这样? 谁能帮我用PB做一个学籍管理系统 大家都来发表意见:我因为职业道德问题,被迫辞职 谁能开导开导小弟,各位大哥帮帮忙吧。我真没得混了。 在VB中如何把图片存储到SQL Server 的数据库中 请问CDialogBar用鼠标拖动改变其大小(这时其大小并没变化)时,将触发什么事件? capboy:为什么我加入了memfile.h后编译回出这样的错误: 我为什么在2000svr下,安装realserver7.0,装不上???(请高手帮忙。) 如何编写象datagrid一样的控件?大家给点建议。 jb6中怎么象JDK中一样编译类哦? 关于非阻塞通信的一个问题!(BSD系统,非WSA...) 哪里有power builder 8.0正式版的下载 我为什么在2000svr下,安装realserver7.0,装不上???, 想用opengl作动画,那本书好?谢啦! 如何才能实现类似PHOTOSHOP的标尺? 有没有方法可以获得所有的消息常量? 各位大虾,请问如何抓屏,就是只抓窗口内容的那种,感激不尽 这样define有什么好处? 对同不端口能不能用多个socket与多台机器建立通信?? 如何判断DataSet中是否为空~!! 求用TAPI通讯示例! 一个很好的访问统计系统,但是希望高手能修改的更完善一点 ACCESS的问题 大家都是怎么管理记录的唯一性的啊? 苦恼………… 怎样截获窗口的最小化、最大化、关闭按钮和双击窗体的标题栏的响应事件??? 如何判断DataSet中是否为空~!! 有没有人在用或会用FreeBSD,能不能回个话? 哪里有pb8.0正式版下载? crystal report 8.0装完之后,为什么在PROJECT ADD里找不到crystal report? ListView的背景怎么改变?要求显示的内容为透明的? 我想找个工作,请指教! 重复这个字符为什么不能运行呢? 能不能这样访问property? 一种杀虫剂是由农药好水按1比50的质量比配制而成的,现有农药8、5千克,需要加水多少千克? 黑色铁粉暴露在空气中能迅速燃烧生成红色的三氧化二铁粉末,该反应的化学方程式是 怎么区分氧化剂与还原剂 配制一种杀虫剂,己知农药与水的比是1.2比50,现在要配制这种杀虫剂1024千克,需要农药多少千克? 求大神解速度谢谢 数字助听器与模拟助听器有什么不同吗? 服装厂原计划用15天加工服装,由于每天比原计划多加工4件,结果10天就完成了任务.原计划每天加工多少见服装? 判断一对一错 1.同一种元素有不同氧化值,不同氧化值物种所组成的电对,其标准电极电势不同.2.气态物质的标准电极电势一般是指气体处在273K、101KPa的电极电势. 如何计算标准电极电势? 黑洞可以改变时间.可以改变形体大小?这个很奇妙.这绝对的违反来人类科学常理,有点像 动画片 机器猫的 “时间穿梭机” 和 “形体缩放筒” .被黑洞吸引过去后.时间变的缓慢.连一个银河系 氧化还原性与标准电极电势物质的氧化性或者还原性是不是和他的电极电势正相关啊,知道的给说下谢 标准电极电势的定义 什么化学药在空气中会冒烟 有关月球黑洞 计算(CuS/Cu)的标准电极电势;已知(Cu(2+)/Cu(+))、(Cu(+)/Cu)的电极电势分别为0.15V、0.52V,另外CuS的溶度积为7.94*10^(-36) 用什么化学药可以把铅变成水?那位能人告诉我?~~~! 电极电势越大,其电对氧化态物质的氧化能力__? 标准电极电势中的"标准"是指什么条件 什么化学药物能除水臭味 如果月球变成了等质量的黑洞,会发生什么? 化学计算条件电极电势已知298K时,E标准(H3AsO4/H3AsO3)=0.0575V,计算在0.10mol/L HCl溶液中电对H3AsO4/H3AsO3的条件电极电势.也不知道活度系数,但答案是求物质组份的,我更加迷惑,思路很混乱, (3a-ab+7)-(-4a+2ab+7) 银河中心的黑洞,太阳,地球将在2012年12月21日连成一条直线科学家说这种情况25800年出现一次,玛雅人知道这是可怕的,那么25800年前发生了什么请参考史实精确回答,不要掺杂个人感情色彩生逢 键线式 然后帮我用软件画出来是三个乙醛 在一定条件下反应的结果好像是 求告诉我系统命名 还有 用好看点的画图软件帮我画出来下~匀称点 也可以不用画!只要系统命名哦! 人类如何才可以进化?未来的人类会进化吗?会进化成什么样? 黑洞与月球的关系 比较下面氧化还原电对的标准电极电势大小已知 Ag2CrO4的Ksp是1.1*10-12次方,而AgCl的Ksp是1.8*10-10次方,比较E (Ag2CrO4/Ag(与E (AgCl/Ag)谁大谁小,Ksp是溶度积 人类在未来的一千年里能否造出可以进化人类的机器吗 农药杀虫剂都有什么牌子的 关于氧化还原反应与电极电势的问题.如何依据电极电势判断一个氧化还原反应是否能进行?. 红色粉末除了铜粉,氧化铁粉外还有什么. 请英文高手帮手--农药杀虫剂本产品杀虫机理独特,添加高活性渗透因子和解抗因子,具有很强的触杀和胃毒作用.害虫一旦接触药剂即麻痹中枢神经,继而使虫体蛋白凝固,堵塞虫体气孔,通过干 乘除法为什么有无符号数和带符号数指令的区分 CO还原氧化铁时红色粉末变成黑色 这句话错在哪? 喝洗衣粉会引起发烧等症状?多大几率?几天能好?不要骂我!迫不得已(不能装病,只能真发烧)吃退烧药可以吗? 就是第一道题 杀虫剂由农药和水1:50的质量比配制成的,现有农药8.5kg,要水多少? 喝洗衣粉水会发烧吗?我想发烧啊!喝洗衣粉水会不会中毒,或者肚子痛,胃痛等.真心想发烧啊?如果喝了洗衣粉水会发烧,吃抗生素是不是有效. 如图,1,2,4,望告诉我详细理由(>^ω^ 高中所有氧化剂、还原剂总结(按强弱排列)还有常见需要知道摩尔质量的物质都有什么 吃洗衣粉会发烧吗?量大概多少?加醋一起会好一些吗?吃一点就要洗胃啊? 求大神告诉我这是哪款丰田啊 如何判断氧化剂和还原剂的强弱和氧化还原反应进行的方向 判断下列物质哪些可以做氧化剂,哪些可以做还原剂,哪些即可以做氧化剂又可以做还原剂Cl- Cl2 H+ F2 Ag+ H2O2 Fe2+ MnO2 应该怎么判断 ASC码 与 数的区别 电对的电极电势越小,其氧化型得电子的倾向就越小,是越强的() 氧化剂还是还原剂?求教. H2O2+I2==2HIO的氧化剂和还原剂是什么 怎么区分还原剂氧化剂Cao+3C→CaC2+CO中的氧化剂还原剂怎么区分 根据化学式如何判断氧化剂 还原剂的强弱 Cl2 +2KI=2KCl +I2 那个是氧化剂?那个是氧化产物?那个是还原剂?那个是还原产物? 逆战打塔防用爆炸和燃烧哪个箭头抢分高 衣服吊牌上 175/92A 什么意思我知道175是 175CM穿的 92A什么意思 1.金属粉末为什么能在空气中燃烧?若加工成纳米技术会怎样?2.粉尘在什么情况下会发生爆炸?四中初三的童鞋们都很需要吧. 逆战,塔防 爆炸箭头和燃烧箭头可以都带吗. 衣服上175,92A, 把一包黑色粉末隔绝空气加强热,有红色固体生成,同时产生能使澄清石灰水变浑浊的气体,由此可知该黑色粉末中一定含有的物质是_______________.变化中有关的化学方程式有:______________,_________ 又是氧化剂又是还原剂的怎么分辨 衬衫175-92A(52)是指什么?如题! 一辆质量为4吨的汽车匀速经过一半径为50米的凸形桥.(g=10m/s2)1.汽车若能安全驶过此桥,它的速度范围是多少?2.若汽车经最高点时对桥的压力等于它重力的一半,求此时汽车的速度多大? 全数字助听器与模拟助听器有什么区别?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘