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

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

 

 

 

 

 

改进VB的驱动器列表框 给TreeView控件添加弹式菜单 -VB资料 计算从开机到现在用了多少秒-VB资料 将立体的ListView标题栏转换成平面式的标题栏 -VB资料 禁用窗体上所有控件 -VB资料 拷贝或移动列表框或组合框中的内容-VB资料 利用VB5开发ActiveX控件 利用VB三维面板控件设计流动条 浅谈用VB6.0编写BO程序 巧用Visual Basic的TIMER控件 VB取得控件绝对Top值 VB如何解决VB中的Grid 控件的打印问题 VB如果自定义 MsgBox 的按钮,标题等 VB如何创建数据绑定控件。 VB如何解决VB中的Grid控件的打印问题 VB如何强制文件对话框再次读取正确的磁盘? VB如何取得RichTextBox控件中光标所在行的值? VB如何设定 MsgBox 在若干时间之后若无回应則自动关闭? VB如何使用VB控件Commom Dialog VB如何用VB6写COM组件(二) VB如何用VB6写COM组件(一) VB如何在VB中使用Delphi的控件 VB如何在运行时动态增加控件 显示和隐藏鼠标-VB资料 VB用ActiveX Control Pad VB用API函数改进ListView 控件的显示效果 用VB6.0中文版进行DHTML程序开发 用VB编写标准CGI程序 用VB编写留言板 用VB播放FLASH动画 用VB开发进程管理软件 软件发布:网页快拷 软件发布:股海点金 软件发布:超级视频采集器 软件发布:网图 2001 软件发布:沸点群发邮件系统 软件发布:邮箱巡捕器 软件发布:功能强大易用的FTP服务器软件(XFTPSVR) 软件发布:邮件监听 软件发布:远程主机管理 软件发布:疯狂俄罗斯【4人网络版】0.26b1 软件发布:拼图 软件发布:凯蒂神卜2001 哪位高手作过网站建设?请帮忙!!! 软件发布:五子棋大战 光驱的问题 软件发布:扑克(版本:36.0,玩法的数量和版本号一样) 软件发布:鸿森万能证件打印系统 软件发布:密码盗窃器(超小版:30k) 软件发布:寝室多人共享上网计时计费器 软件发布:美萍安全卫士密码破解器 软件发布:整人蛀虫 SQL SERVER存储过程的问题!!!! 软件发布:词痴 软件发布:自动关机 软件发布:南易彩票选号系统 pfc基类庫是纯英字,谁有中文的。 软件发布:精灵英文输入法(写代码助手) 软件发布:QQSpy密码探测器98版 for 0425 高手请,为何在不同地方打开对话框会有不同的结果呢? 软件发布:《商务导航》 软件发布:amp player 豪华版 如何关闭XCOPY打开的窗口,详细一点 请援手:pfc程序如何再升级?(关于版本更新) 谁是高手,一个事务处理问题。 大家来聊聊:JBUILDER5比JUILDER4在那方面改进了!? 我们这个破烂小公司成天TMD瞎折腾! 根据用户名和密码登陆的问题! 大家来说一下,中程和高程证书在找工作时作用怎样 Dialog上放了一个group box,请问如何动态改变group box框框中的整个颜色?急呀! 用程序向表中插数据的问题? 怎样制作一个类似日历的控件?快快快! 做个调查:在上海delphi的前景如何?现在工资怎么样? 如何给graph控件的values赋值. c++Builder的悲哀历程,求助帮忙,各位大虾多指点 建议封杀e_lion,影响看贴情绪!杀无赦!!! 请教高手:我用vc6.0向导生成了一个Utility Project,不想用MFC AppWizard(exe)生成的基本类,可我无法编译我写的cpp(带winMain函数)文件,为何? 无任何理由,第一个进来者300分。当场结帐。 各位,是如何调试自己编写的servlet的,我使用jswdk每次,修改servlet后都要重启一次服务器,有没有什么好法子。 不看不知道。 在写servlet时,如果要输出一段文字的问题。 “瑞星2001病毒实时间控装载失败”? 你哥哥的生日在三月份吗?是的.在3月12日.那天,是植树节.英语翻译. 教室里的男生人数是女生人数的三倍,后来走出去18名男生,这时教室里的男女生人数一样多.原来男女生各多少人 育英小学原来男、女生人数的比是7:5,后来由转来12名同学,这时男、女人数的比是9:7学校现有女生多少人 为推广普通话设计一条宣传标语,要运用一种修辞手法, 1:教室里男生是女生数的3倍,走出去18名男生后,教室里男女生人数相同,原来男生女生各有多少(用方程解,把方程步骤写出来)2:一队少先队员乘船过河时,如果每船做15人,还剩9人没上船,如 六年级400名学生参加植树活动,计划每个男生植树10棵,每个女生植树8棵,实际植数时调出20%的男生弄卫生结果男女植树一样多,实际植树多少棵 一辆卡车运石头,晴天每天可以运20次,雨天每天可以运12次,他一连运了112次,平均每天运14次,问这几天中有几天晴天,几天雨天?不用方程。 为推广普通话设计两条宣传标语 要求:紧扣主题 不超过十五个字 运用一种修辞手法 教室里男生是女生的80%,后来又进来20名女生,男生是女生的60%,男女生现在各有多少人? 一辆卡车给工地运砖,晴天每天可运12次,雨天每天可运8次,在三周时间里,共运了220次.这3周里晴天和雨天 推广普通话标语 教室里女同学的人数是男同学的3倍,又进来8个男同学后,女同学的人数还比男同学多6人.教室里有男女各多少人? 一辆汽车运矿石,晴天每天可运14次,雨天每天只呢运3次,这辆汽车运了17天,共运了139次,这些天有多少天天简单明了的要算是 [非常之急]推广普通话的标语对不起,按错回车键,现开始写详细内容:要短小精致的,出处不限(不要拿知道已经有的啦,越快越好,可能视回答情况加分哦!补充内容:我都看过的啦,来条不一样 教室里女同学的人数是男同学的3倍,又进来8个男同学后,女同学的人数还比男同学多6人.教室里原有男、女同学各几人? 一辆卡车运矿石,晴天每天可以运16吨,雨天每天可运11次,这辆卡车一连几天共运了195次,平均每天运13次,这几天中几天是雨天,几天是晴天?假设这几天都是晴天不能用方程 关于推普的标语麻烦各位了.要有创意的,幽默的. 教室里女同学的人数是男同学的3倍,又进来8个男同学后,女同学的人数还比男同学多6人,教室里原来有男女同学各多少人? 松鼠妈妈采松果,晴天可以采20个,雨天只能采十个.他一连几天采了120个,平均每天采12个这几天有几个雨天 以读书为话题写一条标语,至少运用一种修辞手法 美术组有男女若干名,已知女生人数的3分之1和男生人数的5分之1是21人,女生人数的4分之1和男生人数的5分之1是18人,男,女生各有多少人? 小松鼠采松子,雨天每天采12个,晴天每天可采20个.它一连几天采了112个松子,平均每天采14个,问这几天当问这几天当中有几天是晴天要用假设法 为营造书香校园氛围,请你以读书为话题拟写一条标语,至少用一条修辞手法. 某校美术组有102人,男生比女生多25分之1,男女生各多少人? 小松鼠跟妈妈采松子,他们晴天每天采30个,雨天每天采24个,采了一周后,他们发现晴天比雨天少采了6个,这周的晴天和雨天各有多少天? 安全教育的宣传标语,(用上一种修辞手法) 学校合唱队有50人,其中男生和女生人数的比是2:3,男女生各有多少人算式 请问;小松鼠采松子,晴天每天18粒,雨天每天采12粒,12天共采了204粒松子,在这期间有几天是雨天.;要列式. 拟标题(至少用一种修辞手法)某中学为帮助贫困山区的失学儿重返课堂,要在全校展开一次献爱心捐款、捐物、捐书活动.请你为这次活动拟一条校园标语(至少用一种修辞手法) 某小学原来男女生的比是5:7,后来又转来15名女生,这时男女生的比是2:3学校现有男生多少名?算式或解方程,但解方程最好是一元一次方程 松鼠采松果,晴天每天可采20个,雨天每天可才采12个,它一连几天采了112个松果,平均每天采14个,问这几天当中有几天是雨天? 为了营造读书的氛围,请你引用一句名言作为活动的主题标语.名言中至少包含一种修辞手法 1.某小学原来男女生的比是7:5,后来又转来12名女生,这时男女生的比是9:7,学校现有男生多少名?第一题不要用方程解!给我解释一下为什么这么做,2.用1,2,……,9这9个数字排成没有重复数字的九位 小松鼠采松果,晴天可以采35个,雨天可以采22个,它13天共采了403个松果.这期间晴天有多少天?(用方程解 男女生有若干人,男生与女生之比为人数4:3,后来女生走了12人,此时男生人数是女生的2倍求原男女生人数列方程,不算 某小学原有男女生的比是7:5,后来转来12名女生,这时男女生的比是9:7,学校现有男生多少名? 松鼠妈妈采松子晴天可以采20个雨天可以采12个他一连几天采了112个平均每天采14个问有几个晴天几个阴天 某班有男女人数的比为4:3,后来女生走了12名,这时男生人数恰好是女生的2倍,求原来男女生人数? 某小学原来男女生的比是7:5,后来又转来12名学生,这时男女生的比是9:7,学校现有男生多少名 植树节期间,某某单位在一段长10分之9千米的路上从头到尾等距离栽了46棵树,则相邻两棵树的距离是多少千米? 男女生有若干人男生与女生人数之比四比三后来走了十二名女生,这时男生人数恰好是女生人数的2倍,求原男生与女生各有多少人? 学校举行庆“六一”男女生大合唱,原计划合唱对中女生人数占合唱队总人数的60%,后来又增加了5名男生.这时女生和男生的比是6:5.合唱队原来有男生多少名? 今年植树节,学校参加植树活动,成活了250棵,还有8棵没有成活.这批树的成活率是多少?求算式! 阅览室里有男女生若干人,男生与女生若干人,男生与女生的人数之比为四比三,后来有十二名女生走了,这时,男生人数恰好是女生人数的二倍,求原来的男生女生的人数. 学校举行庆“建党90周年”大合唱,原计划合唱队中的女教师人数占合唱队总人数的40%,后来考虑到合唱效果,将其中5名女教师换成了5名男教师,这时女教师人数占总人数的30%.合唱队共有多少名 我国的植树节为什么定于3月12日? 某校六年级男生人数是女生人数的四分之三,后来转进3名女生,这时男生人数是女生人数的三分之二.现在这个班有多少名学生? 学校举行庆“六一”男女生大合唱,原计划合唱队中女生人数占合唱队总人数的40%,后来考虑到合唱效果(下将其中5名女生换成5名男生,这是女生与男生人数的比是3:7.合唱队共有男女生多少 植树节为什么订在3月12日 某校六年级男生人数是女生人数的2/3,后来转进2名男生,转走3名女生,这样男生人数是女生人数的3/4.原来 合唱队中男生人数是女生人数的5/6,后来又增加了3名女生,此时男生人数占合唱队总人数的5/12,合唱队现有男女生各多少人 英汉互译 1.国庆节2.五一劳动节3.植树节 某校六年级男生人数是女生人数的2/3,后来有转进2名男生,转轴3名女生,这是男生某校六年级男生人数是女生人数的2/3,后来有转进2名男生,转轴3名女生,这是男生人数是女生人数的75%。该校 同学们植树,如果每人植的数量是相同的,那么有14棵树没人植,如果每人植9棵,那么最最后一个同学就少3棵,有多少同学植多少棵? 关于植树节英语日记.用过去式写一篇关于植树节和朋友去植树的过程,5句话以上.最好带有翻译.跪谢! 1、某班男女人数比是4:3,后来又转走2名男生,这时男女人数比6:5,女生有多少人?2、男职工比全厂职工的5分之3多60人,女职工是男职工的3分之1,一共有职工多少人?用算式,不要方程,麻烦大家了. 学校春季植树,有14棵树没有成活,成活率是95%,这次春季植树一共植了多少棵树? 用英文翻译:你的祖母的生日是什么时候?7月12日 你的生日是什么时候?8月17日,你呢?3月12日,植树节 某班原来男生是女生的2/5,后来转来一名男生,这时男女生人数之比是3:7,问,男女生个多少人?帮下我! 六年级一班15人参加植树活动,男生每人栽4颗,女生每人栽3颗,共栽52颗树,男生女生各来了多少人?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn