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

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

 

 

 

 

 

用VisualBasic制作半透明窗体 运行时改变控件大小的两种方法-VB资料 运行中隐藏/显示窗口标题栏-VB资料 在ListBox适当设定水平滚动条的宽度-VB资料 在VB中利用API实现窗体的平滑显示 在vb中让控件大小和位置随着表单的大小成比例变化的方法 在VB中实现闪动标题栏 在VB中实现位图的透明放置 在VB中使用数据窗体设计器插件 在VB中制作单独程序封面的两种方法 在VB中制作透明按钮 在Visual Basic中如何拖动窗体或控件 在Visual Basic中显示动态运行进度 在菜单中加入图标 -VB资料 在程序中调用关闭Windows对话框-VB资料 在任务栏中显示无边框窗体的图标-VB资料 在系统菜单上添加自定义菜单项 -VB资料 在运行时动态生成多个相同的控件?-VB资料 在最小化状态时提供提示 -VB资料 暂时禁止窗口更新-VB资料 VB怎样得到文本框(TextBox)中的文本行数? 制造出透明的Form -VB资料 VB制作半透明窗体和形状不规则的窗体 VB制作方向按钮 VB制作渐变的窗口背景色 字体闪烁 -VB资料 自动改变控件大小-VB资料 自制IE风格按纽控件-VB资料 VB6.0中通过MSChart控件调用数据库 用VB6实现动态增减控件 ActiveX控件的创建-VB资料 请问用java编程能实现数据采集的程序并进行传输(即c/s模式)吗? 请问什么命令找开一个窗体的? 请问:如何从文件中获取icon并得到HBITMAP句柄? 如何在客户端打开一个word文件 MVP是个什么概念???? linux启动不了,Bringup loopback interface时出错,请问是什么原因? 帮帮忙!! 我海军一艘潜艇失事 70名官兵不幸全部遇难!! 明天朋友结婚,征集整人的法子 是谁删除了我贴?? 而且没有跟我说一声!!! 白天工作,晚上溜狗,爽呀!比大暑天喝了冰镇雪碧还爽! 我的jsp服务器是iis+TOMCAT+win2000pro 不知怎的每次用不了多久就显示出 网页无法显示 目前访问该 Web 站点的用户过多,我只是自已用怎么 终于有星了,高兴,散分(第一次散分,请斑竹手下留情) 我的刚装的2000进入启动界面时,进度条读到2/3时就蓝屏了! 请问在运行时向ActiveX控件中添加ActiveX控件的方法是什么? 高手请进:如何在WinNT以上系统进行BIOS读取! 毕业设计的问题,请各位大哥帮小弟一个忙 备份与恢复 数据备份与恢复 我用win2k,下载了php4.3.1,extension_dir是c:\php\ext 可是里面没有php_gd.dll,怎么办,到哪里可以down一个补上? 帮我一下:解决中文问题 新手问题:怎么在用ATL COM WIZARD已生成的dll加入MFC 请问如何删除系统? warton给大家散分来了! 求助,请问哪儿提供的域名空间最好? 新手上路,VB中用ODBC连接ACCESS 关于ORACLE中(多)表的备份和恢复问题 MM``狂给分^*^ 找人一同研究JUnit对于数据库的测试架构 怎样在程序中动态生成数据库(内存库)?求救高手 请问,怎样用本机作web服务器? 这样的夜晚 想起一些故人.... 各位的jbuilder是用什么命令运行的 刚学者求问 python+CGI 如何获得客户端IP Win2000上, 对话框没能弹出到桌面顶层 在静态上下文中不能引用非静态变量? 有没有高手可以举例讲解一下self的各种用法? 一个很困惑的问题:文字处理软件中,字体大小改变时,字符的高度,宽度怎么变化? 移动硬盘在重装系统时忘记拔下来。结果给误删了,求助!没有格式化的! 怎样创建自己的 Cursor ? 请问一下 这个是什么意思 public Properties() { this(null)} 在SQL7中日志满了,如何清除日志. ?????????? 一个编程习惯上的问题 为中国争口气!投中国的长城和布达拉宫一票!!恳请置顶! 菜鸟问题4。。。。 网上现在有没有用ASP.NET做的实例 vc.net为什么没classwizard 有关CDC的一个问题,有代码,请指教! 要陪老婆,兄弟们,给我顶住,我先闪了,..... javascript 能否取得客户端的IP? 伊朗议长拉里贾尼:美伊关系改善为时尚奥巴马“网络水军”利用推特打医保舆论帮总统“解围”专门紧盯政治异见者 奥日媒:安倍上任后已打13次高尔夫 展穆尔西出庭高喊“我是总统”东京股市日经股指微涨俄罗斯惊现一专杀老年女性杀人狂 两年男友不肯吃麦当劳 女友开车将其辗过3日本研发机器人摇滚乐队:“鼓手”长6日拟将化妆品等商品列入外国游客免税购摩洛哥一架客机在蒙特利尔机场起火 5印度火星项目负责人祈祷发射成功 称导俄罗斯大胆盗贼偷警察大楼 部分武器及美国务卿克里访埃及 美官员称或恢复对不想脱外套 美国3岁女童被托儿所长活奥巴马被指政治光环不再 支持率与声望一客机在蒙特利尔机场失火被迫疏散 致日本一17岁少年将伙伴推下河 称没有郭声琨:加强防控把暴力恐怖活动摧毁在新疆日报:始终筑牢反分裂思想防线新加坡:见习飞行员遇车祸 获赔留学费济南:公交所属部分公交卡发售网点放假潍城法院试水“家事法庭”,3个月“撮菏泽将全力推进河航道项目建设徐州慧斌联手陆欣文旅以\"文旅\"重留学快问参加EDUclub华南国际教菏泽汽车西站至定陶新增108路公交线潍坊17村入选省旅游扶贫村威海:女子视频吞药,民警定位解救审计署:加大国企及其领导审计 对内幕瓜达尔积极打造中巴经济走廊“桥头堡”开年热剧大盘点,用创维55G7观剧更金瑞龙荣获 “2016年度科技金融公北京首家京东之家盛大开业 顺义区顾客天舟一号“产房”首度曝光看这袋鼠的一身腱子肉,一定是健身狂魔H5风光不再?究竟什么样的H5才算成创维Q8:匠心工艺铸就黑金品质如何快速检查背在身后的宝宝醒没醒?杨阳洋当哥哥了!杨威抱二胎:宝妈辛苦水管防冻保温就找它 青岛三百社区设供55G7霸屏2017年体育竞技,打造
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘