??xml version="1.0" encoding="utf-8" standalone="yes"?>精品久久久久久无码人妻蜜桃,久久无码中文字幕东京热,色综合久久久久综合体桃花网 http://www.shnenglu.com/cxiaojia/厚d 博学 求真 臛_
The bright moon and breeze zh-cn Tue, 06 May 2025 20:53:22 GMT Tue, 06 May 2025 20:53:22 GMT 60 重新认识JavaScript http://www.shnenglu.com/cxiaojia/archive/2013/07/30/202240.htmlC加 C加 Tue, 30 Jul 2013 04:19:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/07/30/202240.html http://www.shnenglu.com/cxiaojia/comments/202240.html http://www.shnenglu.com/cxiaojia/archive/2013/07/30/202240.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/202240.html http://www.shnenglu.com/cxiaojia/services/trackbacks/202240.html 公司准备启动的一个手渔R目,服务器端准备使用|易的开源框架pomelo。pomelo是基于Node.js的高性能,分布式游戏服务器框架。它包括基础的开发框架和相关的扩展组Ӟ库和工具包)Q可以帮助你省去游戏开发枯燥中的重复劳动和底层逻辑的开发?pomelo不但适用于游戏服务器开发, 也可用于开发高实时web应用Q它的分布式架构可以使pomelo比普通的实时web框架扩展性更好?br /> |易的架构师们选择了node.js作ؓ服务器端架构的核心,说明了Node.js作ؓ后端的Javascriptq行环境一定有它自q优越性?br /> 提到JavascriptQ大安先想到的是日怋用的览器,C览器包含了各种lgQ包括渲染引擎、Javascript引擎{,其中Javascript引擎负责解释执行|页中的Javascript代码。作为Web前端最重要的语a之一QJavascript一直是前端工程师的专利。不q,Node.js是一个后端的Javascriptq行环境Q支持的pȝ包括Lnux、Windows、MacQ,q意味着你可以编写系l或者服务器端的Javascript代码Q交lNode.js来解释执行?br /> Node.js支持的语a是JavaScrpitQ之所以选择JavaScrpit作ؓ服务器端q行语言理由如下Q?br /> 1.Javascript作ؓ前端工程师的d语言Q在技术社Z有相当的号召力。而且Q随着Web技术的不断发展Q特别是前端的重要性增加,不少前端工程师开始试?#8221;后台应用“Q在许多采用Node.js的企业中Q工E师都表C因Z惯了JavascriptQ所以选择Node.js?br /> 2.Javascript的匿名函数和闭包Ҏ非帔R合事g驱动、异步编E,从helloworld例子中我们可以看到回调函数采用了匿名函数的Ş式来实现Q很方便。闭包的作用则更大,看下面的代码CZQ?br />var hostRequest = http.request(requestOptions,function (response) { var responseHTML =''; response.on('data', function (chunk) { responseHTML = responseHTML + chunk; }); response.on('end',function (){ console.log(responseHTML); // do something useful }); });
在上面的代码中,我们需要在end事g中处理responseHTML变量Q由于Javascript的闭包特性,我们可以在两个回调函C外定义responseHTML变量Q然后在data事g对应的回调函C不断修改其|q最l在end事g中访问处理?br /> 3.Javascript在动态语a中性能较好Q有开发h员对Javacript、Python、Ruby{动态语a做了性能分析Q发现Javascript的性能要好于其他语aQ再加上V8引擎也是同类的佼D,所以Node.js的性能也受益其中?br /> JavaScript不仅在服务器端开始流行,在游戏客L~程斚w也成Z一个很重要的选择。就在不久前Q目前非常流行的一个手游引擎cocos2d-x也推ZJavaScript版本。引用创始h王哲的一句话Q如果说C++最靠谱的话Q那么Lua应该是最行Q而Javascript是最有前景?img src ="http://www.shnenglu.com/cxiaojia/aggbug/202240.html" width = "1" height = "1" /> ]]>由dota说游戏技能设?转蝲) http://www.shnenglu.com/cxiaojia/archive/2013/05/29/200680.htmlC加 C加 Wed, 29 May 2013 07:18:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/05/29/200680.html http://www.shnenglu.com/cxiaojia/comments/200680.html http://www.shnenglu.com/cxiaojia/archive/2013/05/29/200680.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/200680.html http://www.shnenglu.com/cxiaojia/services/trackbacks/200680.html 转自Q?a >http://blog.sina.com.cn/s/blog_4bb3f8270100ephf.html游戏的技能设计是增加游戏可玩性的重要方式之一?br /> 虽然在实际工作中Q大多遇到的情况应该是程序无法实现或者是因效率不够而放弃。但在一些网总及单机游戏中Q技能枯燥的现象也屡见不鲜?br /> 本文借鉴于DOTA的技能设计说P探讨游戏中技能设计的思\与方向?br /> 技能可以暂时或者永q改变游戏中各种元素数倹{?br /> q些元素几乎是构成游戏或者角色的基本元素比如HP.MP.力量、敏捗智力、{w速度、移动速度、视野、碰撞体U、天气、地形、等{?br /> 而所谓的技能就是可让玩家用之后短暂或者永久改变这些元素的东西?br /> 技能设计的味性也在此?br /> 一个技能所讑֮的元素可以直接媄响玩家的心态、或者说是用这个技能的U极性?br /> 如果游戏中出现几个、直到若q个无法引v玩家U极性的技能的话,那么׃影响玩家Ҏ体游戏的U极性?br /> 而当我们设计技能的时候,p从迎合玩家的心态入手来设计游戏中的技能?br /> 下面只是整合出我暂时所能想到的元素Q排名不分优先程度?br /> 1.视觉听觉的n受:享受Q是的,是q样。玩家在玩游戏就是一Un受的q程Q满他的需要就会让他有享受的感觉。音乐与术Ҏ是最直接刺激直觉听觉Q媄响玩家心情的元素?br /> 术Ҏq不光是华丽越好,重要的是一定要做到W合技能的设计。如果技能是月神剑,Ҏ是个火焰形态的法球发出d不太协调了。又好像是变形术Q如果你使用变Ş术之后仅仅是改变了对方的模型大小的话Q也l对不会有那U把别h变成动物的快感了。而伴随着华丽的特效把敌hLQL会更加让人热血沸腾。这U效果当然还要配合适合的弹道以及速度。。。等{?br /> x不仅可以增加玩家的带入感Q还可以l游戏增加更多的味性。比如玩DOTA的时候,听到有h使用N步的声音Q而周围一个队友都没有。或者是在没有视野的地方Q却可以听到有h在练野的打斗声?br /> ȝ来说x和音乐是最直观影响玩家心情的元素?br /> 2.多样性:如果每个技能都是单一伤害Q或者仅仅是伤害以及常规的DEBUFF。那么也q当于同时降低了游戏的可玩性。这里就需要组合各U元素的改变来创造出各种好玩的技能了?br /> 比如黑暗贤者的真空技能。就是整合了改变敌方坐标以及HP的元素、暗夜魔王可以通过改变天气来与自己的技能组合来增加自己的属性。幽g刃则是在造成伤害的同时还能改变地形属性。或者是末日守卫的死亡,增加了数字判定的额外伤害。地I编l者的~地则是改变基础Ud速度、是否可见以及碰撞之后受C害的整合 q些技能都是多样元素的重组Q多改变了额外的元素Q则让游戏变得更加有׃性?br /> 沙王的穿刺(自己向前I刺Q对自己Ud路径中的敌h造成伤害眩晕Q同时瞬间改变自׃|。点d面施放) 与老虎的蟩跃(向英雄模型的前方向蟩跃,跌q后增加X范围内友方单位的d速度与移动速度。) 敌法的闪烁(点击地面施放Q蟩跃至该地点) qd刺客的突袭(指向性法术,点击一个目标蟩跃至目标的n边,q且增加下几ơ攻ȝd速度。) 其中都是有相同的元素Q在之基上又增加了其他元素的讑֮。这样即便是同类型的效果Q也可以通过不同的方式实现?br /> 利用各种元素的组合就可以创造出各种形态各异的技能。游戏的׃性亦是在此?br /> 3.实用性与q性:一个音效与Ҏ非常炫目Qƈ且让人感觉很有意思的技能还需要一个让玩家频繁使用的要素。就是实用性。维持各个技能与英雄搭配之间的^衡,才能让技能变得有实用性。所以把实用性与q性放在了一赗也怽会发C些游戏中有不具备实用性的技能,仅仅凭借着华丽的特效而存在。但q种技能也只会是一点点。。。没多少玩家愿意喜欢一个只有华而不实的技能的英雄的。击败其他玩家永q是大多数玩家最大的q求?br /> 之后惌的一些,是怎样通过改变游戏元素的各U组合来创造出多样性技能的思\?br /> 你还不知道怎样讑֮技能?那就再次举例。。?br /> 你可以把增加敌h单体Ud速度、攻击速度与增加自己攻击速度、移动速度l合h。这样就是死灵飞龙的黄泉之\了?br /> 你可以把矩ŞAOE伤害Q与眩晕效果与地形改变组合。那样就变成了牛牛的沟壑?br /> 你可以设定一个AOE技能,对范围内的目标造成伤害Q此时多加一个判定,是Ҏ?的倍数的造成额外的伤実뀂这样就是一个AOE与末日守卫技能的l合了?br /> 你想增加一个RP性质极强的技能?L骑士的C与圣骑士的T不就是么Q还x加RP一点? 把死亡一指的伤害X1.5Q范围施?#8212;—对范围内的随Z个敌方单位造成伤害。这样不RP了? 游戏中技能的l合会更多的增加游戏的娱乐性,正是因ؓ各种l合Q所以DOTA?5个英雄都能大攑օ彩?br /> 技能怎样ȝ合?也许DOTA中技能与技能元素直接互相媄响的英雄q不是非常多Q但是亦都有联系。下面就来设定一个新的英雄?br /> 我们先定义这个英雄的定位。他是一个力量型的英雄,q且有一定的q击与逃跑能力Q懂得保护自己和增加Ҏ所受到的伤実뀂而他需要用怎样的技能来表现他的定位呢? 增加Ud速度与攻击速度的技能,是最适合q击与逃跑的,但是太过单调。减免伤害与增加敌方单位受到的伤害都是已l有cM的技能了的。如何来讑֮一个具备这些条件而又与以往不同的英雄技能呢Q?br /> 减免伤害的方式有多种Q增加自q护甲Q或者直接减受C害的具体数|以及直接减免受到伤害的百分比{等很多方式。。?br /> 增加敌方受到伤害的方式亦有很多种Q比如DEBUFFQ让敌h受到额外的伤宻I可以直接的,单次的,或者是像苑一L累一定时间的?br /> 下面我们所想的是用怎样的技能把两种方式l合h?br /> 技?Q增加移动与d速度Q这个就是基Q但是不能光靠这个技能去表现。需要让其他的技能也可以实现q击与逃跑 技?Q挟持对方英雄,英雄紧脓着敌方英雄单位Q无法进行攻MUdQ在q之间受到的所有伤害都会{到敌方英雄n上。这样就满了英雄设定中所有的要求。但是这栯定有一定的问题Q就是挟持之后,敌方玩家都不再攻击被挟持的单位。且挟持对友方单位的dq没有增q的作用。这L技能还是缺乏一些实用性。这样就出现了技?. 技?Q永久性被动技能,减少被挟持英雄的Ud速度。如果仅仅是q样的话Q那么依旧ƈ不是多样化。于是又增加了可切换的功能。姿?是减自׃及自己所挟持目标所受到的所有伤宻I姿?是增加自׃及自己所挟持目标的所有伤実뀂这样亦是通过原来DOTA没有的方式完成了减免伤害与增加对Ҏ受到伤害的方式?br /> q样一个徏议的新英雄概念就出来了。。。之后就是具体设定的调整Q比如被挟持的单位是处于什么状态,以及具体数值的讑֮{等。。?br /> MQ技能的讑֮是多样化的,多到思\永远不会被局限。永q都可以有更多更有意思的技能被讑֮出来?br /> 此文只是写的一些技能设定的思\Q没有考虑M实现问题。。。此斚wq是不要拍我了?br /> 惛_l一些苦g不知道怎样讑֮好玩的技能的新手。。。希望对他们有一点点帮助?/span>
]]> ACE前摄器Proactor最好的讲解Q{载) http://www.shnenglu.com/cxiaojia/archive/2013/04/12/199385.htmlC加 C加 Fri, 12 Apr 2013 09:43:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/04/12/199385.html http://www.shnenglu.com/cxiaojia/comments/199385.html http://www.shnenglu.com/cxiaojia/archive/2013/04/12/199385.html#Feedback 3 http://www.shnenglu.com/cxiaojia/comments/commentRss/199385.html http://www.shnenglu.com/cxiaojia/services/trackbacks/199385.html 转自Q?a >http://blog.csdn.net/caisini_vc/article/details/4474910 把这两天做Proactor的一些经验和心得写一下,可能会给一些h帮助?br /> Proactor是异步模式的|络处理器,ACE中叫?#8220;前摄?#8221;?br /> 先讲几个概念Q?br /> 前摄器(ProactorQ-异步的事件多路分d、处理器Q是核心处理cR启动后?个线E组成(你不需要关心这三个U程Q我只是让你知道一下有q回事存在)?br /> 接受器(AcceptorQ-用于服务端,监听在一个端口上Q接受用Lh?br /> q接器(ConnectorQ-用于客户端,去连接远E的监听。当Ӟ如果q程是ACE写的Q就是Acceptor?br /> 异步模式Q即非阻塞模式。网l的传输速度一般来讲ؓ10Mbps?00Mbps?000Mbps。拿千兆|来_实际的传输速度?000Mbps/8大概?28KB左右。我们的CPU一般ؓP4 3.0GHZQ如果是32位的处理器,一U钟大概可以处理6G的字节,那么Q?28KB的网l速度是远q及不上处理器的速度的。网l发送数据是一位一位发送出ȝQ如果CPU{在q里Q发送完成函数才l束Q那么,处理器浪费了大量旉在网l传输上?br /> 操作pȝ提供了异步的模式来传输网l数据,工作模式卻I应用E序把要发送的数据交给操作pȝQ操作系l把数据攑֜pȝ~冲区后告诉应用程序OK了,我帮你发Q应用程序该q嘛q嘛厅R操作系l发送完成后Q会l应用系l一个回执,告诉应用E序Q刚才那个包发送完成了Q?br /> 举个例子Q你有几邮件和包裹要发Q最有效率的办法是什么?你把邮g和包裹及交给dQdMM_好了Q你帮你发,你忙dQ然后你d作了。过了一会,dMM打电话告诉你Q?#8220;刚才我叫快递公司的人来了,把你的包裹发出去了。邮局的h也来了,取走了邮Ӟ攑ֿ好了”。同P如果你知道今天会有包ҎQ比如你在淘宝上购物了,你能成天{在dQ你应该告诉dMMQ?#8220;今天可能有我的一个快递,你帮我收一下,晚上请你肯d基!”。MMQ?#8220;看在肯得基的面子上,帮你收了”。某个时_MM打电话来了:“帅哥Q你的包裹到了,我帮你签收了Q快来拿吧?#8221; 因ؓ操作pȝ是很有效率的Q所有,他在后台收发是很快的。应用程序也很简单。Proactor是q种异步模式的。Proactor是dMMQACE_Service_Handle是d代ؓ收发邮g的公司流E?/p>我们看一个实例:
// *********************************************************** class TPTCPAsynchServerImpl : public ACE_Service_Handler { public : TPTCPAsynchServerImpl( void ); ~ TPTCPAsynchServerImpl( void ); virtual void open (ACE_HANDLE handle, ACE_Message_Block & message_block); virtual void handle_read_stream ( const ACE_Asynch_Read_Stream::Result & result); virtual void handle_write_stream ( const ACE_Asynch_Write_Stream::Result & result); virtual void handle_time_out ( const ACE_Time_Value & tv, const void * act = 0 ); private : int initiate_read_stream ( const ACE_Asynch_Read_Stream::Result & result); ACE_Asynch_Read_Stream rs_; ACE_Asynch_Write_Stream ws_; };
q个例子从ACE_Service_Handlerl承q来QACE_Service_Handle主要是定义了一些回调函数?br />1?virtual void open (ACE_HANDLE handle, ACE_Message_Block &message_block); 当有客户端连接上来,q接建立成功后Proactor会调用这个方法?/p>
2?virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result); 当用戯ȝ数据d了后Q调用这个方?/p>
3、virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result); 当用戯写的数据在网卡上发送成功后QProactor会回调这个方?/p>
4?virtual void handle_time_out (const ACE_Time_Value &tv, const void *act=0); 当用戯定的旉到期了,q个Ҏ会被调用?/p>
q跟和dMM的联l方法是不是一LQ?/p>
对还~点东西Q缺怎么向dMM交待d的方法。下面看看:
首先Q创Z个监听器?/p>
ACE_Asynch_Acceptor<TPTCPAsynchServerImpl> acceptor_; 看到没,是我们刚才写的c,因ؓ他承了回调接口Qƈ实现了自已的代码Q模板中ACE_Asynch_Acceptor会在合适的时候回调这些方法?/p>
//创徏一个地址对象 ACE_INET_Addr addr(port, ip); acceptor_.open (addr, 8 * 1024, 1); Open后,开始监听了。其它的Q向Proactor注册一些事件的事模板类中都替你做了Q你不需要做很多事?br /> 那么Q已l开始监听了Q我的程序从哪里开始呢Q对于一个服务程序来ԌE序是被用户的连接驱动的Q一个用L序想和通讯Q必d创徏q接Q就是Socket中的connect操作。这个操作Proactor会替我们做一些工作,当连接创建完成后Q上面讲的OpenҎ会被调用Q我们看看OpenҎ中都有些什么代码:
void TPTCPAsynchServerImpl::open (ACE_HANDLE handle, ACE_Message_Block & message_block) { ACE_DEBUG ((LM_DEBUG, " %N:%l:TPTCPAsynchServerImpl::open() " )); // 构造读?/span> if (rs_.open ( * this , handle) == - 1 ) { ACE_ERROR ((LM_ERROR, " %N:%l: " , " TPTCPAsynchServerImpl::open() Error " )); return ; } // 构造写?/span> if (ws_.open( * this , handle) == - 1 ) { ACE_ERROR ((LM_ERROR, " %N:%l: " , " TPTCPAsynchServerImpl::open() Error " )); return ; } // 获取客户端连接地址和端?/span> ACE_INET_Addr addr; ACE_SOCK_SEQPACK_Association ass = ACE_SOCK_SEQPACK_Association(handle); size_t addr_size = 1 ; ass.get_local_addrs( & addr,addr_size); this -> server_ -> onClientConnect(( int )handle, addr.get_ip_address(), addr.get_port_number()); // 如果客户q接时同时提交了数据Q需要伪造一个结果,然后呼叫M?/span> if (message_block.length () != 0 ) { // ACE_DEBUG((LM_DEBUG, "message_block.length() != 0 ")); // 复制消息?/span> ACE_Message_Block & duplicate = * message_block.duplicate (); // 伪造读l果Q以便进行读完成回调 ACE_Asynch_Read_Stream_Result_Impl * fake_result = ACE_Proactor::instance ()-> create_asynch_read_stream_result ( this -> proxy (), this -> handle_, duplicate, 1024 , 0 , ACE_INVALID_HANDLE, 0 , 0 ); size_t bytes_transferred = message_block.length (); // Accept事g处理完成Qwr_ptr指针会被向前UdQ将其移动到开始位|?/span> duplicate.wr_ptr (duplicate.wr_ptr () - bytes_transferred); // q个Ҏ调用回调函?/span> fake_result -> complete (message_block.length (), 1 , 0 ); // 销毁伪造的ȝ?/span> delete fake_result; } // 否则Q通知底层Q准备读取用h?br /> // 创徏一个消息块。这个消息块用于从套接字中异步?nbsp; ACE_Message_Block * mb = 0 ; ACE_NEW (mb, ACE_Message_Block (_bufSize)); if (rs_.read ( * mb, mb -> size () - 1 ) == - 1 ) { delete mb; ACE_ERROR ((LM_ERROR, " %N:%l:open init read failed! " )); return ; } }
我们看到Q首先创Z两个,是前面cd义中定义的一个异步写,一个异步读。以后对|络的读和写通过q两个流q行。我q给Z一D读客户端地址和端口的代码。然后是d客户Connect可能附带的数据,那段代码不用看懂Q以后用照抄就行。然后就?/p>
if (rs_.read (*mb, mb->size () - 1) == -1) { delete mb; ACE_ERROR ((LM_ERROR, "%N:%l:open init read failed!")); return ; }
q段代码使用LMD|据。这D代码就是向dMM交待Q我要收包裹Q收好了叫我Q?br />也就是说Q这D代?9%的可能是M出数据的Q只是向Proactor注册ȝ事gQ具体的{待、读取操作由Proactor读,d了,回调Handle_Read_StreamҎ。ACE_Message_Block是消息块Q数据就是存攑֜消息块中的?br />下面看看Handle_Read_StreamҎ的代码:
void TPTCPAsynchServerImpl::handle_read_stream ( const ACE_Asynch_Read_Stream::Result & result) { result.message_block ().rd_ptr ()[result.bytes_transferred ()] = ' /0 ' ; ACE_DEBUG ((LM_DEBUG, " ********************/n " )); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " bytes_to_read " , result.bytes_to_read ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " handle " , result.handle ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " bytes_transfered " , result.bytes_transferred ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " act " , (u_long) result.act ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " success " , result.success ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " completion_key " , (u_long) result.completion_key ())); ACE_DEBUG ((LM_DEBUG, " %s = %d/n " , " error " , result.error ())); ACE_DEBUG ((LM_DEBUG, " ********************/n " )); result.message_block().release(); if ( this -> initiate_read_stream (result) == - 1 ) { ACE_ERROR((LM_ERROR, " %N:%l:read stream failed!connection closed, remove it:%d/n " , result.handle())); closeConnection(result.handle()); } }
q个函数被调用,p明有数据已经d了,包裹已经在d了。Proactor比dMMq好Q给你送上门了Q数据就在Result里,上面演示了Result中的数据。然后把消息块释放了Q然后调用initiate_read_streaml箋监听|络上可能到来的数据。看看initiate_read_stream好了Q?/p>
int TPTCPAsynchServerImpl::initiate_read_stream ( const ACE_Asynch_Read_Stream::Result & result) { ACE_DEBUG((LM_TRACE, " %N:%l:TPTCPAsynchServerImpl::initiate_read_stream() " )); // 创徏一个消息块。这个消息块用于从套接字中异步?nbsp; ACE_Message_Block * mb = new ACE_Message_Block(_bufSize); if (mb == NULL) { ACE_DEBUG((LM_ERROR, " %N:%l:can't allock ACE_Message_Block. " )); return - 1 ; } if (rs_.read ( * mb, mb -> size () - 1 ) == - 1 ) { delete mb; ACE_ERROR_RETURN ((LM_ERROR, " %N:%l:rs->read() failed, clientID=%d " , result.handle()), - 1 ); } return 0 ; }
代码很简单,是创徏一个新的消息块Q然后用读注册一个读消息可以了?/p>
到此为止QProactor的读程很清楚了吧?
下面再说一个写程?/p>
写流E其实更单,在Q意想向客L写数据的地方Q调用相应代码就行了Q比如,我们提供了SendDataҎ来发送数据,在Q意想发送数据的地方调用SendDatap了,SendData的代码如下:
int TPTCPAsynchServerImpl::sendData( int clientID, const char * data, int dataLen, unsigned int & id) { ACE_DEBUG((LM_DEBUG, " TPTCPAsynchServerImpl::sendData(void) " )); ACE_Message_Block * mb; ACE_NEW_RETURN(mb, ACE_Message_Block(dataLen + 1 ), - 1 ); mb -> wr_ptr(( char * )data); ACE_OS::memcpy(mb -> base (),( char * )data, dataLen); id = GlobleSingleton::instance() -> getIndex(); mb -> msg_type(( int )id); // 向操作系l发送数?/span> if (connection -> ws -> write ( * mb , dataLen ) == - 1 ) { ACE_ERROR_RETURN((LM_ERROR, " %N:%l:sendData failed! clientID=%d " , clientID), - 1 ); } return 0 ; }
单说Q就是创Z一个消息块Q把用户数据拯q来Q然后调用写WS向Proactor发送一个Write事g可以了Q发送成功后QHandle_write_handle会被调用Q看一下:
void TPTCPAsynchServerImpl::handle_write_stream (const ACE_Asynch_Write_Stream::Result & result) { ACE_DEBUG ((LM_DEBUG, " handle_write_stream called " )); // Reset pointers. result.message_block ().rd_ptr (result.message_block ().rd_ptr () - result.bytes_transferred ()); ACE_DEBUG ((LM_DEBUG, " ******************** " )); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " bytes_to_write " , result.bytes_to_write ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " handle " , result.handle ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " bytes_transfered " , result.bytes_transferred ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " act " , (u_long) result.act ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " success " , result.success ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " completion_key " , (u_long) result.completion_key ())); ACE_DEBUG ((LM_DEBUG, " %s = %d " , " error " , result.error ())); ACE_DEBUG ((LM_DEBUG, " ******************** " )); #if 0 ACE_DEBUG ((LM_DEBUG, " %s = %s " , " message_block " , result.message_block ().rd_ptr ())); #endif // Release message block. result.message_block ().release (); }
代码中用了result中发数据Q然后把消息块释放了Q就q么单?/p>
////////////////////////////////////////////////////////////////////////////////////////////////////
q是单的proactor用法Q当Ӟ复杂也基本就q样用。所谓不基本的不是Proactor的内容,而是服务器编E本w的ȝ。比如说Q多个连接的理、重发机制、发送队列等{,q都不是ACE的内宏V这些要大家自己思考了Qƈd?/p>
在这里,我要说几个重要的问题Q连接的理。Acceptor是一个类Q但是在每一个连接,Proactor都用了某U办法创Z一个实例,所以,q接理的群集类一定不能在AcceptorcMQ不然得到的l果是始终只有一条记录。因为每个Acceptor都有一个实例,实例对应一个连接,集cM每个实例一个了。要采取的方法是一个全局的容器对象就可以了。比如我q个c:
typedef ACE_Map_Manager < ACE_HANDLE, ConnectionBean * , ACE_Null_Mutex > ConnectionMap; typedef ACE_Map_Iterator < ACE_HANDLE, ConnectionBean * , ACE_Null_Mutex > ConnectionIterator; typedef ACE_Map_Entry < ACE_HANDLE, ConnectionBean *> ConnectionEntry; class Globle { public : Globle( void ); ~ Globle( void ); ITPServer * server_; ConnectionMap _connections; unsigned getIndex( void ); long getTimerId( void ); private : unsigned int index_; long timerId_; }; typedef ACE_Singleton < Globle, ACE_Null_Mutex > GlobleSingleton;
我用ACE的Singleton模板创徏q个c,每一个Acceptor要用ConnectionMapQ都使用q里的_connectionsQ方法如?Q?br /> GlobleSingleton::instance()->connection.bind()......
q个问题可是我花费了2天时间找出来的,怽同仁不可不戒啊,l点掌声Q)
]]>ACE|络~程W记Q?Q:ACE自适配通信环境 http://www.shnenglu.com/cxiaojia/archive/2013/04/08/199198.htmlC加 C加 Mon, 08 Apr 2013 01:48:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/04/08/199198.html http://www.shnenglu.com/cxiaojia/comments/199198.html http://www.shnenglu.com/cxiaojia/archive/2013/04/08/199198.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/199198.html http://www.shnenglu.com/cxiaojia/services/trackbacks/199198.html 介绍 ACE自适配通信环境QADAPTIVE Communication EnvironmentQ是可以自由使用、开放源码的面向对象QOOQ构ӞFrameworkQ,在其中实C许多用于q发通信软g的核心模式。ACE提供了一l丰富的可复用C++Wrapper FacadeQ包装外观)和构架组Ӟ可跨多U^台完成通用的通信软gdQ其中包括:事g多\分离和事件处理器分派、信号处理、服务初始化、进E间通信、共享内存管理、消息\由、分布式服务动态(重)配置、ƈ发执行和同步Q等{?br /> ACE的目标用h高性能和实旉信服务和应用的开发者。它化了使用q程间通信、事件多路分R显式动态链接和q发的OO|络应用和服务的开发。此外,通过服务在运行时与应用的动态链接,ACEqɾpȝ的配|和重配|得以自动化?br /> 好处
增强可移植?/strong>Q在ACElg的帮助下Q很Ҏ在一UOSq_上编写ƈ发网l应用,然后快速地它们移植到各种其他的OSq_上。而且Q因为ACE是开放源码的自由软gQ你无需担心被锁定在特定的操作系l^台或~译器上?br />更好的Y件质量: ACE的设计用了许多可提高Y件质量的关键模式Q这些质量因素包括通信软g灉|性、可扩展性、可复用性和模块性?br /> 更高的效率和可预性: ACEl仔l设计,支持q泛的应用服务质量(QoSQ需求,包括延迟敏感应用的低响应{待旉、高带宽应用的高性能Q以及实时应用的可预性?br />更容易{换到标准的高U中间gQ?/strong>TAO使用了ACE提供的可复用lg和模式。它是CORBA的开发源码、遵循标准的实现Qƈ为高性能和实时系l作了优化。ؓ此,ACE和TAO被设计ؓ能良好地协同工作Q以提供全面的中间g解决Ҏ?br />体系l构 OS适配层: ACE底层Q和OS的API相关的部分。这部分ACE把不同类型的OS接口l一hQ让ACE的高层摆脱^台的依赖性。适配层增Z代码的可UL性?br />C++包装层: ACE中间层,主要功能的实现部分。包括ƈ发和同步、IPC、内存管理组件、定时器cR容器类、信号处理、文件系l组件和U程理?br />构架和模式层Q?/strong>ACE高层Q架构和模式部分。它们的基础是若q针对特定通信软g领域的设计模式。包括事件处理、连接或服务初始化组件、流lg和服务配|组件?br />
]]> ACE|络~程之ACE_NEW_RETURNQACE_NEWQACE_NEW_NORETURN http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198838.htmlC加 C加 Tue, 26 Mar 2013 07:26:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198838.html http://www.shnenglu.com/cxiaojia/comments/198838.html http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198838.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/198838.html http://www.shnenglu.com/cxiaojia/services/trackbacks/198838.html OS_Memory.h是这样定义的?br /># if defined (ACE_HAS_NEW_NOTHROW) # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \ } while (0) # define ACE_NEW(POINTER,CONSTRUCTOR) \ do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; return ; } \ } while (0) # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; } \ } while (0) # else # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ do { try { POINTER = new CONSTRUCTOR; } \ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return RET_VAL; } \ } while (0) # define ACE_NEW(POINTER,CONSTRUCTOR) \ do { try { POINTER = new CONSTRUCTOR; } \ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return ; } \ } while (0) # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ do { try { POINTER = new CONSTRUCTOR; } \ catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; } \ } while (0) # endif /* ACE_HAS_NEW_NOTHROW */ #else /* ACE_NEW_THROWS_EXCEPTIONS */ # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ do { POINTER = new CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \ } while (0) # define ACE_NEW(POINTER,CONSTRUCTOR) \ do { POINTER = new CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; return ; } \ } while (0) # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ do { POINTER = new CONSTRUCTOR; \ if (POINTER == 0) { errno = ENOMEM; } \ } while (0)
以上是用宏定义替换的表达式,功能都是用一个POINTER指针new一个CONSTRUCTOR实例Q内部做了一些错误信息的标志和异常处理?br />宏ifelse对^台的不同q行了分,每个q_下都有三Unew的方法,他们的区别是return?br />每个宏定义都用到了do{}while(0)Q是因ؓ宏只能替换一句表辑ּQ而你用do{}while(0)可以方便的把多个表达式集中v来?img src ="http://www.shnenglu.com/cxiaojia/aggbug/198838.html" width = "1" height = "1" /> ]]> socketd与非dQ同步与异步、I/O模型(? http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198831.htmlC加 C加 Tue, 26 Mar 2013 05:36:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198831.html http://www.shnenglu.com/cxiaojia/comments/198831.html http://www.shnenglu.com/cxiaojia/archive/2013/03/26/198831.html#Feedback 1 http://www.shnenglu.com/cxiaojia/comments/commentRss/198831.html http://www.shnenglu.com/cxiaojia/services/trackbacks/198831.html 转自Q?a >http://blog.csdn.net/hguisu/article/details/7453390 1. 概念理解
在进行网l编E时Q我们常常见?span style="margin: 0px; padding: 0px; font-family: Arial, Helvetica, sans-serif, 宋体; font-size: 12px; line-height: 16px; text-indent: 24px;">同步(Sync)/异步(Async)Q阻?Block)/非阻?Unblock) 四种调用方式Q?/span>同步Q?/span> 所谓同步,是在发Z个功能调用时Q在没有得到l果之前Q该调用׃q回?/span>也就是必M件一件事?/strong> , {前一件做完了才能做下一件事?/span>
例如普?span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">B/S模式Q同步)Q提交请?span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">->{待服务器处?span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">->处理完毕q回 q个期间客户端浏览器不能qQ何事
异步Q?/span> 异步的概念和同步相对。当一个异步过E调用发出后Q调用者不能立d到结果。实际处理这个调用的部g在完成后Q通过状态、通知和回调来通知调用者?/span>
例如 ajaxhQ?/span>异步Q?/span>: h通过事g触发 -> 服务器处理(q是览器仍然可以作其他事情Q?/span>-> 处理完毕
d d调用是指调用l果q回之前Q当前线E会被挂PU程q入非可执行状态,在这个状态下Qcpu不会l线E分配时间片Q即U程暂停q行Q。函数只有在得到l果之后才会q回?/span>
有h也许会把d调用和同步调用等同v来,实际上他是不同的。对于同 步调用来_很多时候当前线E还是激zȝQ只是从逻辑上当前函数没有返回而已?/span> 例如Q我们在s ocket 中调用r ecv 函数Q如果缓冲区中没有数 据,q个函数׃一直等待,直到有数据才q回。而此Ӟ当前U程q会l箋处理各种各样的消息?/span>
非阻?/strong> 非阻塞和d的概늛对应Q指在不能立d到结果之前,该函C会阻塞当前线E,而会立刻q回?/span>对象的阻塞模式和d函数调用 对象是否处于d模式和函数是不是d调用有很强的相关性,但是q不是一一对应的。阻塞对象上可以有非d的调用方式,我们可以通过一定的 API 去轮询状 态,在适当的时候调用阻塞函敎ͼ可以避免阻塞。而对于非d对象Q调用特D的函数也可以进入阻塞调用。函?/span>select 是q样的一个例子?/span>
1. 同步Q就是我调用一个功能,该功能没有结束前Q我ȝl果?/span>2. 异步Q就?span style="margin: 0px; padding: 0px; line-height: 20px;">我调用一个功能, 不需要知道该功能l果Q该功能有结果后通知我(回调通知Q?/span>3. dQ? 是调用我(函数Q,?span style="margin: 0px; padding: 0px; line-height: 20px;">Q函敎ͼ 没有接收完数据或者没有得到结果之前,我不会返回?/span>4. 非阻塞, 是调用?span style="margin: 0px; padding: 0px; line-height: 20px;">Q函敎ͼ Q我Q函敎ͼ 立即q回Q?span style="margin: 0px; padding: 0px; line-height: 20px;">通过select通知调用?/span>
同步IO和异步IO的区别就在于Q?span style="margin: 0px; padding: 0px; color: #ff0000;">数据拯的时候进E是否阻塞!
dIO和非dIO的区别就在于Q?/span>应用E序的调用是否立卌回!
对于举个单c/s 模式Q?/span>
同步Q?/span>提交h->{待服务器处?>处理完毕q回q个期间客户端浏览器不能qQ何事异步Q?/span>h通过事g触发->服务器处理(q是览器仍然可以作其他事情Q?>处理完毕
同步和异步都只针对于本机SOCKET而言的?/span>
同步和异?d和非d,有些L,其实它们完全不是一回事,而且它们修饰的对象也不相同?br style="margin: 0px; padding: 0px;" />d和非d是指当进E访问的数据如果未qA,q程是否需要等? 单说q相当于函数内部的实现区?/span>,也就是未qA时是直接q回q是{待qA;
而同步和异步?/span>指访问数据的机制 ,同步一般指dhq等待I/O操作完毕的方?当数据就l后在读写的时候必阻?区别qA与读写二个阶D?同步的读写必阻?,异步则指dh数据后便可以l箋处理其它d,随后{待I/O,操作完毕的通知,q可以ɘq程在数据读写时也不d?{待"通知")
1. Linux下的五种I/O模型
1)dI/OQblocking I/OQ?br style="margin: 0px; padding: 0px;" />2)非阻塞I/O Qnonblocking I/OQ?/span> 3) I/O复用(select 和poll) QI/O multiplexingQ?/span> 4)信号驱动I/O Qsignal driven I/O (SIGIO)Q?/span> 5)异步I/O Qasynchronous I/O (the POSIX aio_functions)Q?/span>
前四U都是同步,只有最后一U才是异步IO?/p>
dI/O模型Q?/span> 介:q程?/span>一直阻?/span>Q直到数据拷贝完?/span>
应用E序调用一个IO函数Q导致应用程序阻塞,{待数据准备好?如果数据没有准备好,一直等?#8230;.数据准备好了Q从内核拯到用L?IO函数q回成功指示?/span>
dI/O模型图: 在调用recv()/recvfromQ)函数Ӟ发生在内怸{待数据和复制数据的q程?/span>
当调用recv()函数Ӟpȝ首先查是否有准备好的数据。如果数据没有准备好Q那么系l就处于{待状态。当数据准备好后Q将数据从系l缓冲区复制到用L_然后该函数返回。在套接应用E序中,当调用recv()函数Ӟ未必用户I间已l存在数据,那么此时recv()函数׃处于{待状态?br style="margin: 0px; padding: 0px;" />
当用socket()函数和WSASocket()函数创徏套接字时Q默认的套接字都是阻塞的。这意味着当调用Windows Sockets API不能立即完成ӞU程处于{待状态,直到操作完成?/span>
q不是所有Windows Sockets API以阻塞套接字为参数调用都会发生阻塞。例如,以阻塞模式的套接字ؓ参数调用bind()、listen()函数Ӟ函数会立卌回。将可能d套接字的Windows Sockets API调用分ؓ以下四种:
1Q输入操作: recv()、recvfrom()、WSARecv()和WSARecvfrom()函数。以d套接字ؓ参数调用该函数接收数据。如果此时套接字~冲区内没有数据可读Q则调用U程在数据到来前一直睡眠?/span>
2Q输出操作: send()、sendto()、WSASend()和WSASendto()函数。以d套接字ؓ参数调用该函数发送数据。如果套接字~冲区没有可用空_U程会一直睡眠,直到有空间?/span>
3Q接受连接:accept()和WSAAcept()函数。以d套接字ؓ参数调用该函敎ͼ{待接受Ҏ的连接请求。如果此时没有连接请求,U程׃q入睡眠状态?/span>
4Q外接:connect()和WSAConnect()函数。对于TCPq接Q客L以阻塞套接字为参敎ͼ调用该函数向服务器发赯接。该函数在收到服务器的应{前Q不会返回。这意味着TCPq接M{待臛_到服务器的一ơ往q时间?/span>
使用d模式的套接字Q开发网l程序比较简单,Ҏ实现。当希望能够立即发送和接收数据Q且处理的套接字数量比较的情况下,使用d模式来开发网l程序比较合适?/span>
d模式套接字的不表现为,在大量徏立好的套接字U程之间q行通信时比较困难。当使用“生?消费?#8221;模型开发网l程序时Qؓ每个套接字都分别分配一个读U程、一个处理数据线E和一个用于同步的事gQ那么这h疑加大系l的开销。其最大的~点是当希望同时处理大量套接字时Q将无从下手Q其扩展性很?/span>
非阻塞IO模型
介:非阻塞IO通过q程反复调用IO函数Q?/span>多次pȝ调用Qƈ马上q回 Q; 在数据拷贝的q程中,q程是阻塞的 Q?/span>
我们把一个SOCKET接口讄为非d是告诉内核Q当所h的I/O操作无法完成Ӟ不要进E睡眠,而是q回一个错误。这h们的I/O操作函数不断的试数据是否已经准备好,如果没有准备好,l箋试Q直到数据准备好为止。在q个不断试的过E中Q会大量的占用CPU的时间?/span>
?span style="margin: 0px; padding: 0px; font-size: 14px;">SOCKET 讄为非d模式Q即通知pȝ内核Q在调用Windows Sockets APIӞ不要让线E睡眠,而应该让函数立即q回。在q回Ӟ该函数返回一个错误代码。图所C,一个非d模式套接字多ơ调用recv()函数的过E。前三次调用recv()函数Ӟ内核数据q没有准备好。因此,该函数立卌回WSAEWOULDBLOCK错误代码。第四次调用recv()函数Ӟ数据已经准备好,被复制到应用E序的缓冲区中,recv()函数q回成功指示Q应用程序开始处理数据?/span>
当用socket()函数和WSASocket()函数创徏套接字时Q默认都是阻塞的。在创徏套接字之后,通过调用ioctlsocket()函数Q将该套接字讄为非d模式。Linux下的函数?fcntl(). 套接字设|ؓ非阻塞模式后Q在调用Windows Sockets API函数Ӟ调用函数会立卌回。大多数情况下,q些函数调用都会调用“p|”Qƈq回WSAEWOULDBLOCK错误代码。说明请求的操作在调用期间内没有旉完成。通常Q应用程序需要重复调用该函数Q直到获得成功返回代码?/span>
需要说明的是ƈ非所有的Windows Sockets API在非d模式下调用,都会q回WSAEWOULDBLOCK错误。例如,以非d模式的套接字为参数调用bind()函数Ӟ׃会返回该错误代码。当Ӟ在调用WSAStartup()函数时更不会q回该错误代码,因ؓ该函数是应用E序W一调用的函敎ͼ当然不会q回q样的错误代码?/span>
要将套接字设|ؓ非阻塞模式,除了使用ioctlsocket()函数之外Q还可以使用WSAAsyncselect()和WSAEventselect()函数。当调用该函数时Q套接字会自动地讄为非d方式?br style="margin: 0px; padding: 0px;" />
׃使用非阻塞套接字在调用函数时Q会l常q回WSAEWOULDBLOCK错误。所以在M时候,都应仔细查返回代码ƈ作好?#8220;p|”的准备。应用程序连l不断地调用q个函数Q直到它q回成功指示为止。上面的E序清单中,在While循环体内不断地调用recv()函数Q以d1024个字节的数据。这U做法很费pȝ资源?/span>
要完成这L操作Q有Z用MSG_PEEK标志调用recv()函数查看~冲Z是否有数据可诅R同Pq种Ҏ也不好。因做法对系l造成的开销是很大的Qƈ且应用程序至要调用recv()函数两次Q才能实际地d数据。较好的做法是,使用套接字的“I/O模型”来判断非d套接字是否可d写?/span>
非阻塞模式套接字与阻塞模式套接字相比Q不Ҏ使用。用非d模式套接字,需要编写更多的代码Q以便在每个Windows Sockets API函数调用中,Ҏ到的WSAEWOULDBLOCK错误q行处理。因此,非阻塞套接字便显得有些难于用?/span>
但是Q非d套接字在控制建立的多个连接,在数据的收发量不均,旉不定Ӟ明显h优势。这U套接字在用上存在一定难度,但只要排除了q些困难Q它在功能上q是非常强大的。通常情况下,可考虑使用套接字的“I/O模型”Q它有助于应用程序通过异步方式Q同时对一个或多个套接字的通信加以理?/span>
IO复用模型Q?/span> 介:主要是select和epollQ对一个IO端口Q两ơ调用,两次q回Q比dIOq没有什么优性;关键是能实现同时对多个IO端口q行监听Q?/span>
I/O复用模型会用到select、poll、epoll函数Q这几个函数也会使进E阻塞,但是和阻塞I/O所不同的的Q这两个函数可以同时d多个I/O操作。而且可以同时对多个读操作Q多个写操作的I/O函数q行,直到有数据可L可写Ӟ才真正调用I/O操作函数 ?/span>
信号驱动IO
介:两次调用Q两ơ返回;
首先我们允许套接口进行信号驱动I/O,q安装一个信号处理函敎ͼq程l箋q行q不d。当数据准备好时Q进E会收到一个SIGIO信号Q可以在信号处理函数中调用I/O操作函数处理数据?/span>
异步IO模型 介:数据拯的时候进E无需d?/span>
当一个异步过E调用发出后Q调用者不能立d到结果。实际处理这个调用的部g在完成后Q通过状态、通知和回调来通知调用者的输入输出操作
同步IO引vq程dQ直至IO操作完成?br style="margin: 0px; padding: 0px;" />异步IO不会引vq程d?br style="margin: 0px; padding: 0px;" />IO复用是先通过select调用d?br style="margin: 0px; padding: 0px;" />
5个I/O模型的比较:
1. select、poll、epoll?br style="margin: 0px; padding: 0px;" />
epoll跟select都能提供多\I/O复用的解x案。在现在的Linux内核里有都能够支持,其中epoll是Linux所ҎQ而select则应该是POSIX所规定Q一般操作系l均有实?/p>
selectQ?/span>
select本质上是通过讄或者检查存放fd标志位的数据l构来进行下一步处理。这h带来的缺ҎQ?/p>
1?单个q程可监视的fd数量被限Ӟ卌监听端口的大有限?br style="margin: 0px; padding: 0px;" />
一般来说这个数目和pȝ内存关系很大Q具体数目可以cat /proc/sys/fs/file-max察看?2位机默认?024个?4位机默认?048.
2?对socketq行扫描时是U性扫描,即采用轮询的ҎQ效率较低:
当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调?不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU旉。如果能l套接字注册某个回调函数Q当他们z跃Ӟ自动完成相关操作Q那避免了轮询Q这正是epoll与kqueue做的?/p>
3、需要维护一个用来存攑֤量fd的数据结构,q样会得用L间和内核I间在传递该l构时复制开销?/p>
pollQ?/span>
poll本质上和select没有区别Q它用户传入的数组拯到内核空_然后查询每个fd对应的设备状态,如果讑֤qA则在讑֤{待队列中加入一ƈl箋遍历Q如果遍历完所有fd后没有发现就l设备,则挂起当前进E,直到讑֤qA或者主动超Ӟ被唤醒后它又要再ơ遍历fd。这个过E经历了多次无谓的遍历?/p>
它没有最大连接数的限Ӟ原因是它是基于链表来存储的,但是同样有一个缺点:
1、大量的fd的数l被整体复制于用h和内核地址I间之间Q而不这L复制是不是有意义?nbsp; 2、pollq有一个特Ҏ“水^触发”Q如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd?/p>epoll:
epoll支持水^触发和边~触发,最大的特点在于边缘触发Q它只告诉进E哪些fd刚刚变ؓ需态,q且只会通知一ơ。还有一个特ҎQepoll使用“事g”的就l通知方式Q通过epoll_ctl注册fdQ一旦该fdqAQ内核就会采用类似callback的回调机制来Ȁz该fdQepoll_wait便可以收到通知
epoll的优点:
1、没有最大ƈ发连接的限制Q?/span> 能打开的FD的上限远大于1024Q?G的内存上能监听约10万个端口Q;2、效率提?/strong> Q不是轮询的方式Q不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数Q?br style="margin: 0px; padding: 0px;" /> 即Epoll最大的优点在于它只管?#8220;z跃”的连接,而跟q接L无关Q因此在实际的网l环境中QEpoll的效率就会远q高于select和poll?/span>
3?nbsp;内存拯 Q利用mmap()文g映射内存加速与内核I间的消息传递;即epoll使用mmap减少复制开销?br style="margin: 0px; padding: 0px;" />select、poll、epoll 区别ȝQ?/span>
1、支持一个进E所能打开的最大连接数
select
单个q程所能打开的最大连接数有FD_SETSIZE宏定义,其大是32个整数的大小Q在32位的机器上,大小是32*32Q同?4位机器上FD_SETSIZE?2*64Q,当然我们可以对进行修改,然后重新~译内核Q但是性能可能会受到媄响,q需要进一步的试?/p>
poll
poll本质上和select没有区别Q但是它没有最大连接数的限Ӟ原因是它是基于链表来存储?/p>
epoll
虽然q接数有上限Q但是很大,1G内存的机器上可以打开10万左右的q接Q?G内存的机器可以打开20万左右的q接
2、FD剧增后带来的IO效率问题
select
因ؓ每次调用旉会对q接q行U性遍历,所以随着FD的增加会造成遍历速度慢的“U性下降性能问题”?/p>
poll
同上
epoll
因ؓepoll内核中实现是Ҏ每个fd上的callback函数来实现的Q只有活跃的socket才会d调用callbackQ所以在z跃socket较少的情况下Q用epoll没有前面两者的U性下降的性能问题Q但是所有socket都很z跃的情况下Q可能会有性能问题?/p>
3?消息传递方?/p>
select
内核需要将消息传递到用户I间Q都需要内核拷贝动?/p>
poll
同上
epoll
epoll通过内核和用L间共享一块内存来实现的?/p>
ȝQ?/span>
lgQ在选择selectQpollQepoll时要Ҏ具体的用场合以及这三种方式的自w特炏V?/p>
1、表面上看epoll的性能最好,但是在连接数ƈ且连接都十分z跃的情况下Qselect和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调?/p>
2?span style="margin: 0px; padding: 0px; color: #000000; background-color: #ffcc00;">select低效是因为每ơ它都需要轮询。但低效也是相对的,视情况而定Q也可通过良好的设计改?/span>
]]>#pragma once ?#ifndef 解析(? http://www.shnenglu.com/cxiaojia/archive/2013/03/18/198526.htmlC加 C加 Mon, 18 Mar 2013 02:28:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/03/18/198526.html http://www.shnenglu.com/cxiaojia/comments/198526.html http://www.shnenglu.com/cxiaojia/archive/2013/03/18/198526.html#Feedback 2 http://www.shnenglu.com/cxiaojia/comments/commentRss/198526.html http://www.shnenglu.com/cxiaojia/services/trackbacks/198526.html 转自Q?/span>http://blog.csdn.net/slimfox/article/details/1565950 Z避免同一个文件被include多次QC/C++中有两种方式Q一U是#ifndef方式Q一U是#pragma once方式。在能够支持q两U方式的~译器上Q二者ƈ没有太大的区别,但是两者仍然还是有一些细微的区别?/span> 方式一Q?/span> #ifndef __SOMEFILE_H__ #define __SOMEFILE_H__ ... ... // 一些声明语?br style="margin: 0px; padding: 0px;" /> #endif 方式二: #pragma once ... ... // 一些声明语?/span> #ifndef的方式依赖于宏名字不能冲H,q不光可以保证同一个文件不会被包含多次Q也能保证内容完全相同的两个文g不会被不心同时包含。当Ӟ~点是如果不同头文件的宏名不小?#8220;撞R”Q可能就会导致头文g明明存在Q编译器却硬说找不到声明的状?#8212;—q种情况有时非常让h抓狂?/span> #pragma once则由~译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文?#8221;是指物理上的一个文Ӟ而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名撞引发的奇怪问题。对应的~点是如果某个头文件有多䆾拯Q本Ҏ不能保证他们不被重复包含。当Ӟ相比宏名撞引发?#8220;找不到声?#8221;的问题,重复包含更容易被发现q修正?/span> #pragma once方式产生?ifndef之后Q因此很多h可能甚至没有听说q。目前看?ifndef更受到推崇。因?ifndef受语a天生的支持,不受~译器的M限制Q?pragma once方式却不受一些较老版本的~译器支持,换言之,它的兼容性不够好。也许,再过几年{旧的编译器ȝ了,q就不是什么问题了?/span> 我还看到一U用法是把两者放在一LQ?/span> #pragma once #ifndef __SOMEFILE_H__ #define __SOMEFILE_H__ ... ... // 一些声明语?br style="margin: 0px; padding: 0px;" /> #endif 看v来似乎是惛_有两者的优点。不q只要用了#ifndef׃有宏名冲H的危险Q所以用两U方法似乎不能带来更多的好处Q倒是会让一些不熟悉的h感到困惑?/span> 选择哪种方式Q应该在了解两种方式的情况下Q视具体情况而定。事实上Q只要有一个合理的U定来避开~点Q我认ؓ哪种方式都是可以接受的。而这个已l不是标准或者编译器的责MQ应当由E序员来搞定?/span> btwQ我看到GNU的一些讨Z乎是打算在GCC 3.4Q及其以后?Q的版本取消?pragma once的支持。不q我手上GCC 3.4.2和GCC 4.1.1仍然支持#pragma onceQ甚x有deprecation warning。VC6及其以后版本亦提供对#pragma once方式的支持。看来这一Ҏ已l稳定下来了?nbsp; ]]> MFC文档序列化实C存和加蝲 http://www.shnenglu.com/cxiaojia/archive/2013/03/02/198177.htmlC加 C加 Sat, 02 Mar 2013 10:04:00 GMT http://www.shnenglu.com/cxiaojia/archive/2013/03/02/198177.html http://www.shnenglu.com/cxiaojia/comments/198177.html http://www.shnenglu.com/cxiaojia/archive/2013/03/02/198177.html#Feedback 2 http://www.shnenglu.com/cxiaojia/comments/commentRss/198177.html http://www.shnenglu.com/cxiaojia/services/trackbacks/198177.html 1、序列化定义
MFC文档 - 视图l构中,序列化机制可以实现内存中对象储存和加载?/span>
序列化机制分为序列化和反序列化,序列化是把内存中的对象以二进制文件的形式存储在磁盘中。反序列化是把序列化后生成的文g恢复到内存?/p>
2?/span>CArchive c?/span>
CArchive没有基类?/span> CArchive允许以一个永久二q制Q通常为磁盘存储)的Ş式保存一个对象的复杂|络Q它可以在对象被删除Ӟq能怹保存。可以从怹存储中装载对象,在内存中重新构造它们。得数据永久保留的q程叫?/span>“ 序列?#8221;?/span> 可以把一个归档对象看作一U二q制。象输入/ 输出一P归档与文件有兛_ƈ允许写缓冲区以及从硬盘读出或d数据。输?/span>/ 输出处理一pd ASCII 字符Q但是归档文件以一U有效率、精l的格式处理二进制对象?/span>
3?/span>CArchive 对象处理基础cd数据
必须在创Z?span style="font-family: 'Times New Roman'">CArchive对象之前Q创Z?/span>CFile 对象。另外,必须信归档文g的装?/span>/ 存储与文件的打开模式是兼容的。每一个文件只限于一个活动归档文件?/span> 当构造一?span style="font-family: 'Times New Roman'">CArchive 对象Ӟ要把它附加给表示一个打开文g的类 CFile Q或zc)的对象上。还要指定归档文件将用于装蝲q是存储?/span>
CZQ?/p>
CFile file( " 1.txt " ,CFile::modeCreate | CFile::modeWrite); // 定义一个文件流对象 CArchive ar( & file,CArchive::store); // 定义一个序列化对象和文件流对象l定q指定归档方式ؓ储存Q加载的方式为CArchive::load int i = 4 ; char ch = ' a ' ; float f = 1.3f ; CString str( " aa " ); ar << i << ch << f << str; // 储存到文?/span>
4?/span>CArchive对象 处理自定义对象类型数?/strong>
CArchive对象不仅可以处理首要cdQ而且q能处理?/span>序列化而设计的Ҏ的类的对象。可以序列化的类有以下特点:
1、必Mؓ CObjectzcR?/span>直接或者间接的l承CObject cR?/span>
2、必重写CObjectcȝSerialize成员函数?/p>
3?/span>使用DECLARE_SERIAL ?/span>IMPLEMENT_SERIAL 宏?/span>
4、必L一个默认构造函?/span>
在Serialize成员函数中完成保存和加蝲的功能?/p>
DECLARE_SERIAL( class_name ) 参数?/span>当前cd?/p>
IMPLEMENT_SERIAL( class_name, base_class_name, wSchema ) W一个参Cؓ当前cdQ第二个参数为父cȝ名,W三个参Cؓ该类的特定整型标?span style="font-family: 'Times New Roman'">,
该标识将用来解序 ( 重新实例?/span>) Q最ؓ0 ?/span>
CZQ?/p>
// DrawBase.h class CDrawBase : public CObject // l承自CObject { public : DECLARE_SERIAL(CDrawBase) // W一个宏的位|,参数为当前类?/span> CDrawBase(); // 必须有一个默认构造函?/span> virtual void onDraw(CDC * pdc); virtual ~ CDrawBase(); public : UINT m_PenStyle; int m_PenWidth; int m_BkMode; int m_BrushStyle; int m_issx; int m_isyy; COLORREF m_PenColor; COLORREF m_BackgroundColor; COLORREF m_BrushColor; CPoint m_ptBegin; CPoint m_ptEnd; public : void Serialize(CArchive & ar); // 重写了Serialize成员函数 } ; // DrawBase.cpp IMPLEMENT_SERIAL(CDrawBase, CObject, 1 ) // W二个宏的位|,W一个参Cؓ当前cdQ第二个参数为父cȝ名,W三个参Cؓ该类的特定整型标?该标识将用来解序(重新实例?Q最ؓ0 void CDrawBase::Serialize(CArchive & ar) { CObject::Serialize(ar); if (ar.IsStoring()) // 保存Q加载ؓar.IsLoading() { ar << m_PenColor << m_PenStyle << m_PenWidth << m_BrushColor << m_BrushStyle << m_issx << m_isyy; } Else // 加蝲 { ar >> m_PenColor >> m_PenStyle >> m_PenWidth >> m_BrushColor >> m_BrushStyle >> m_issx >> m_isyy; } }
重蝲提取Q?span style="font-family: 'Times New Roman'">>>Q和插入Q?/span><< Q是方便的归档编E接口。它支持主要cd?/span>CObject zcR?/span> CArchiveq支持?/span>MFC Windows 套接字类 CSocket ?/span>CSocketFile ~程?/span>IsBufferEmpty 成员函数也支持这U用?/span>
一些集合类也支持序列化Q?span style="font-family: 'Times New Roman'">CObArray,Vector,CPtrArray?/span>
?span style="font-family: 'Times New Roman'">MFC文档 - 视图l构中, Doc cL被系l设定好支持序列化的c,?/span>Doc cM重写 Serialize成员函数 。在函数中对你要保存的对象序列化?/p>
完成之后Q点击菜单栏上的保存和打开可以实现序列化了?/p>
]]>
NoSql数据库学习汇?/title> http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195875.htmlC加 C加 Sat, 01 Dec 2012 15:13:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195875.html http://www.shnenglu.com/cxiaojia/comments/195875.html http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195875.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/195875.html http://www.shnenglu.com/cxiaojia/services/trackbacks/195875.html MongoDB 8天学通MongoDB——W一?基础入门8天学通MongoDB——W二?l说增删查改 8天学通MongoDB——W三?l说高操作 8天学通MongoDB——W四?索引操作 8天学通MongoDB——W五?M复制 8天学通MongoDB——W六?分片技?/a> 8天学通MongoDB——W七?q维技?br /> 8天学通MongoDB——W八?驱动实践 ]]> 8UNosql数据库系l对比(转) http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195865.htmlC加 C加 Sat, 01 Dec 2012 09:12:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195865.html http://www.shnenglu.com/cxiaojia/comments/195865.html http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195865.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/195865.html http://www.shnenglu.com/cxiaojia/services/trackbacks/195865.html 阅读全文 ]]> Nosql入门知识Q{Q?/title> http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195864.htmlC加 C加 Sat, 01 Dec 2012 08:57:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195864.html http://www.shnenglu.com/cxiaojia/comments/195864.html http://www.shnenglu.com/cxiaojia/archive/2012/12/01/195864.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/195864.html http://www.shnenglu.com/cxiaojia/services/trackbacks/195864.html 1. NoSQL其实是关pd数据库相对应的,是no relational 即非关系型数据库Qweb2.0特别是一些用戯问量比较大的|站如:www.taobao.com weibo.com baidu.com
每秒的访问量可能是上万次(10K);传统的关pd数据?mysql oracle 每秒q行10Kơ数据查询还可以勉强应付Q但是如果是每秒10Kơ读写数据库Q因为数据库的数据都是卸载磁盘中Q所以磁盘IO也是支撑不住每秒10K的读写?/p>
在web的架构中Q数据库是最难进行横向扩展的(通过单的d机器和硬Ӟ也就是添加一些服务节Ҏ提高负蝲均衡能力)Q对?*24时在线的网站来_对关pd数据库进行升U和扩展(分布式扩?-分库分表)是非常痛苦的事情Q往往要进行停机维护;但这U对www.taobao.com 来说是非怸陋的事情。[--可不可以d几台服务器然后把复制Q然后进行负载均?-]?/p>
NoSQL 是采用key/value的结构来存储数据Q而且大多数的NoSQL采用内存来存储数据,一D|间后把数据同步到盘中;׃使用内存保存 数据很好地解决了高ƈ发读?/strong>的问题;其次NoSQL提供了根据keyD行横向分?比如Q用户idQ每2000w数据攑ֈ一台数据库服务器中的一张用戯?Q同时实CM数据库互备,q样可以让数据库的动态迁Ud得简单,让数据库服务器的横向扩展变得Ҏ了?/p>
2. 分布式数据库的CAP理论
CAP理论是说 Consistency Q一致性)Q?/span> Availability Q可用性)Q?/span> partition tolerance Q分布)三部分系l;而且Mpȝ只会满两个Q不会有M的系l会同时满q三个条Ӟ在传l的关系型数据库中是C 一致性,但是在满高可用?高ƈ发时效率不高)Q高扩展?分布式数据库q行横向扩展)存在一定的~陷。但是NoSQL在进行设计的时候就是针对ƈ发v量数据存储的情况下进行设计的Q在q种高ƈ发v量数据下数据一致性ƈ不像银行那样保持数据的强一致性,所以NoSQL·攑ּZ致性的q求Q从而达到更高的可用性和扩展性,通过“鸽l原理 ”辑ֈ最l的一致性?/span>
现在的数据库pȝ肯定是同一个时L多个q程Ҏ据库q行d操作Q假讄在有3个进E?A、B、C)Ҏ据库的某表进行操作,
Z致性:A写入的数据xQB、C可以d数据x ׃致性:A写入的数据xQB、C一D|间内M刎ͼ最后会d 最l一致性:是一U特D的一致性,保证在一D|间内没有数据的更斎ͼ但所有的q回都是把最新的数据q回Q?--~存的概念,一D|间后把数据更新到数据库,辑ֈ最l一致性?/span> 3. 哈希法
(1). 哈希法的基本原理:
哈希法的提出和应用背景Q对于一个庞大的字符串数larrayQ给你一个字W串让你判断它是否在q个字符串数l中q找到它Q最好的办法是把这个庞大的字符串数l构建成一个哈希表Q然后在q行查询是否有这个字W串?/span>
(2).构徏hash table的过E:一般是采用一?2的整数来代表一个字W串Q首先这个array的字W串已经存在内存或者磁盘中Q我们要做的只是按照一定的法把每个字W串映射C?2位的整数Q每个int?个字节,在字W串中每个字W都占一个字节;q样徏立了字符串与32位整数的映射Q然后根据程序大设定一个hash table的Size(q个Size保所有的int % Size的值是唯一?-取最大值即?/strong>)Q这个把刚才得到的所有字W串对应?2位整数对q个Sizeq行取模Q这个模值就是此整数在hash table的位|;q个位置与每一个字W串又徏立了一个映关p;q样让你查询q个str是否在array中?
首先Q是把这个strQ用相同的哈希算法进行编?--->映射C?2位的int型数?num 然后Q把q个num % Size 获取此字W串在hash table里面的位|; 然后Q判断hash table 此位|是否已l有数据占用Q如果已l占用说明在array里面有一个字W串对应?2位整Cstr?2位整数相同,在一个字W串对应唯一一?2位整数的前提条g下,p明array里面存在字符串str?/span> int GetHashTablePos(char *lpszString, SOMESTRUCTURE *lpTable, int nTableSize) { //lpszSring--要查询的字符ԌlpTable 哈希表;nTableSize是哈希表的Size int nHash = HashString (lpszString), nHashPos = nHash % nTableSize; if (lpTable[nHashPos].bExists && !strcmp(lpTable[nHashPos].pString, lpszString)) //旉复杂度是O(1) return nHashPos; else return -1; //Error value } (3). 上面的处理方法是假设一个字W串通过一个哈希算法只得到唯一一个hashcode(32为int整数)Q但是如果存在两个整数在同一个哈希算法得到同一个hashcodeQ那q个查询׃正确的,虽然q个可能性比较小Q但实存在q个风险?/div>
采用的解军_法是用多个不同的哈希法来校验,两个str 在三个不同的哈希法得到的hashcode都相同的概率是:1/18889465931478580854784Q可以认为是OK的?/span>
int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize) { const int HASH_OFFSET = 0 , HASH_A = 1 , HASH_B = 2 ; int nHash = HashString (lpszString, HASH_OFFSET); int nHashA = HashString (lpszString, HASH_A); int nHashB = HashString (lpszString, HASH_B); int nHashStart = nHash % nTableSize, nHashPos = nHashStart ; while (lpTable[nHashPos].bExists) { if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos] .nHashB == nHashB) return nHashPos; else nHashPos = (nHashPos + 1) % nTableSize; if (nHashPos == nHashStart) break; } return -1; //Error value } q样可以保证万无一׃Q?/div>
(4). 常见的哈希算法:MD5 SHA SHA-1{都是常用的哈希法Q而且他们都属于合哈希算法,除了混合哈希法q有加法、乘法、除法的哈希法Q?/div>
所以,在比较一个文件是否发生变化的ҎZ可以用最后修Ҏ间来判断Q也可以用其哈希code来比较,比如用MD5来比较,如果其MD5都变化了则文件一定被修改了?br />
4. Tair ~存也是一U?Zkey/value的NoSQLl构开发的一U缓存机Ӟ其实质也是NoSQL数据库,不过是key/valuel构而且是用内存来存储数据,所以用把Tair叫做~存?/span>
5. 关系型数据库的事?ACID)
(1). 事务(Transaction)QTransaction是访问ƈ可能更新数据库中各种数据的一个程序执行单?unit)Q事务一般由高数据语言(C++ Java SQL){写的用L序引LQƈ用begin transaction----end transaction 来界定一个完整的事务
< begin transaction > **** **** **** </ end transaction > 一个完整的事务?span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">begin transaction----end transaction 里面的所有操作组成;在关pd数据库中一个事务可以是一条SQL语句或一lSQL语句或者是一个程序;事务是ƈ发和回滚的基本单位?/span>
(2). 事务的ACID属性:
Atomicity(原子?Q一个事务是一个不可分割的完整单元Q一个transaction里面的所有操作要么都做完Q要么都不做Q当中间一个操作失败把所有已l做的操作都回滚Q?/span> Consistency(一致?Q数据库在一个事务开始前是一致性的Q在q个事务执行完毕后仍然是一致性的Q只是从一个一致性状态到另一个一致性状态;但都是一致性的 Isolation(隔离?Q一个事务的执行不能被其他事务所打扰Q即一个事务内部操作及使用的数据对q发的事务是隔离的,q发执行的事务之间互怸q扰 (不理? !! Durablity(持久?Q也永久?Permanence)Q即一个事务一旦执行完毕,则它Ҏ据库的更新是持久性的Q即不受其他操作的媄响;也就是事务修改了数据库了 q个ACID的属性是关系型数据库(DBMS)非常重要的属性,在执行数据库操作时必LACID属性,其中AI是我们编E中要注意的地方?/span>
]]>
vs2005,vs2008解决d变量d函数dcL脚本错误问题 http://www.shnenglu.com/cxiaojia/archive/2012/11/12/195070.htmlC加 C加 Mon, 12 Nov 2012 04:35:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/11/12/195070.html http://www.shnenglu.com/cxiaojia/comments/195070.html http://www.shnenglu.com/cxiaojia/archive/2012/11/12/195070.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/195070.html http://www.shnenglu.com/cxiaojia/services/trackbacks/195070.html l一个控件添加变量的时候出现的脚本错误问题
解决ҎQ?/span>
1Q?/font> 打开开始菜单,点击q行按钮Q输?/span>regedit Q进入注册表界面
2Q?/font> 扑ֈ目录 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones
3Q?/font> 查看此目录下是否存在 1000 目录Q如果不存在则徏立此目录
4Q?/font> ?/span>1000 目录下创?/span>DWORD |名字?/span>1207 Qgؓ 0
5Q?/font> 重启 vs2005/2008
]]>优先队列Q二叉堆Q模?/title> http://www.shnenglu.com/cxiaojia/archive/2012/09/15/190272.htmlC加 C加 Sat, 15 Sep 2012 06:40:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/09/15/190272.html http://www.shnenglu.com/cxiaojia/comments/190272.html http://www.shnenglu.com/cxiaojia/archive/2012/09/15/190272.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/190272.html http://www.shnenglu.com/cxiaojia/services/trackbacks/190272.html template < class T, int MAX = 100003 > class BinaryHeap { private : int Size; T * Tarr; public : BinaryHeap(); void insert(T x); T deleteMin(); ~ BinaryHeap(); }; template < class T, int MAX > BinaryHeap< T,MAX > ::BinaryHeap() { Tarr = new T[MAX + 1 ]; if (Tarr == NULL) {cout << " 创徏数组p| " << endl; return ;} Size = 0 ; } template < class T, int MAX > void BinaryHeap < T,MAX > ::insert(T x) { ++ Size; if (Size == MAX) return ; int i; for (i = Size;Tarr[i / 2 ] > x;i /= 2 ) Tarr[i] = Tarr[i / 2 ]; Tarr[i] = x; } template < class T, int MAX > T BinaryHeap< T,MAX > ::deleteMin() { if (Size == 0 ) return 0 ; T minem = Tarr[ 1 ]; T lastem = Tarr[Size -- ]; int i,child; for (i = 1 ;i * 2 <= Size;i = child) { child = i * 2 ; if (child != Size - 1 && Tarr[child + 1 ] < Tarr[child]) ++ child; if (lastem > Tarr[child]) Tarr[i] = Tarr[child]; else break ; } Tarr[i] = lastem; return minem; } template < class T, int MAX > BinaryHeap< T,MAX > :: ~ BinaryHeap() { delete[] Tarr; } ]]>
哈希模板 http://www.shnenglu.com/cxiaojia/archive/2012/09/12/190436.htmlC加 C加 Wed, 12 Sep 2012 12:06:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/09/12/190436.html http://www.shnenglu.com/cxiaojia/comments/190436.html http://www.shnenglu.com/cxiaojia/archive/2012/09/12/190436.html#Feedback 0 http://www.shnenglu.com/cxiaojia/comments/commentRss/190436.html http://www.shnenglu.com/cxiaojia/services/trackbacks/190436.html const int MAX=1000003; template <class T>class hash {private : int pos; int next[MAX]; int head[MAX]; T key[MAX];public : hash(); bool search(T x); void push(T x); }; template <class T> hash<T>::hash() { pos=0; memset(next,-1,sizeof (next)); memset(head,-1,sizeof (head)); // memset(key,-1,sizeof(key)); } template <class T> inline bool hash<T>::search(const T x) { int temp=x%MAX; int t=head[temp]; while (t!=-1) { if (key[t]==x) { return 1; } t=next[t]; } return 0; } template <class T> inline void hash<T>::push(const T x) { int temp=x%MAX; if (head[temp]!=-1) { next[pos]=head[temp]; } head[temp]=pos; key[pos]=x; pos++; } ]]>
一天一个shell实例Q?Q定时备份文?/title> http://www.shnenglu.com/cxiaojia/archive/2012/09/07/189789.htmlC加 C加 Fri, 07 Sep 2012 03:00:00 GMT http://www.shnenglu.com/cxiaojia/archive/2012/09/07/189789.html http://www.shnenglu.com/cxiaojia/comments/189789.html http://www.shnenglu.com/cxiaojia/archive/2012/09/07/189789.html#Feedback 1 http://www.shnenglu.com/cxiaojia/comments/commentRss/189789.html http://www.shnenglu.com/cxiaojia/services/trackbacks/189789.html 写一个备份文件的脚本Q利用crontab定时执行?/p>
步骤如下Q?/p>
1Q设|备份目的目?/p>
2Q进入目的目?/p>
3Q获取时_讄备䆾文g?/p>
4Q备份文?/p>
# !/ bin / bash DIRNAME = `ls / root | grep bak` # 1 if [ - z " $DIRNAME " ] # 2 then mkdir / root / bak # 3 fi cd / root / bak # 4 YY= `date +% y` # 5 MM= `date +% m` DD = `date +% d` etc = _etc BACKETC = $YY$MM$DD$etc.tar.gz # 6 tar - zcvf $BACKETC / etc # 7 echo " fileback finished! "
#1Q获取root/bak字符?/p>
#2Q?z选项判断是否为空
#3Q如果ؓI就创徏目录
#4Q进入该目录
#5Q获取当前时?/p>
#6Q设|备份文件名
#7Q将/etc目录下所有文件打包备?/p>
-z 用gizp压羃和解压羃文gQ若加上此选项创徏的压~包Q解压的时候也许要加上此选项
-c 创徏新的?/p>
-v 详细报告tar处理文g的信?/p>
-f 使用压羃文g或设备,该选项通常事必选的
定时执行脚本需要修改etc中的 crontab文g
root@Notebook - PC: / etc# vi crontab # / etc / crontab: system - wide crontab # Unlike any other crontab you don ' t have to run the `crontab ' # command to install the new version when you edit this file # and files in / etc / cron.d. These files also have username fields, # that none of the other crontabs do . SHELL =/ bin / sh PATH =/ usr / local / sbin: / usr / local / bin: / sbin: / bin: / usr / sbin: / usr / bin # m h dom mon dow user command 17 * * * * root cd / && run - parts -- report / etc / cron.hourly 25 6 * * * root test - x / usr / sbin / anacron || ( cd / && run - parts -- report / etc / cron.daily ) 47 6 * * 7 root test - x / usr / sbin / anacron || ( cd / && run - parts -- report / etc / cron.weekly ) 52 6 1 * * root test - x / usr / sbin / anacron || ( cd / && run - parts -- report / etc / cron.monthly ) 0 1 * * * root test4.sh #加上此行Q表C每?时执行脚?nbsp; #
* * * * * #表示每分?/p>
1 * * * * #表示每小时的W一分钟
2 12 * * * #表示每天?2Q?2
0-59/2 * * * * #每两分钟执行一ơQ?/p>
]]>
þøݾƷԴվ |
鶹ŷۺϾþ |
ھƷžžþþþƷ |
Ʒþþž
|
ƷþþþþĻ |
Ʒ91þþþþþ
|
þҹҹ³³ƬӰ |
þ99Ʒþ99ý
|
ݺɫþþۺϲ |
Ʒþþþ
|
˾Ʒþþþþۺ |
һþaþþƷ |
ŷþav |
þþƷAV
|
þþƷһ |
Ʒ۲ӰԺþ |
þþƷ |
aëƬþѲ |
ٸۺϾþĻ |
ۺϾþϵ |
ƷþþþþҰ
|
AVݺɫۺϾþ
|
Ʒþþþþþþþ |
þˬˬƬAV |
99þùۺϾƷ |
þ99Ʒ |
þþþòҰ¸߳ |
99þþƷѹƬ |
ɫۺϾþĻ |
þ99ۺϾƷ |
ɫþþۺľþһ |
ھƷþþӰԺ |
þþۺϾɫۺ̾ |
97Ʒ˾þô߽app |
þvwww |
ھƷ˾þþþӰԺ
|
ھƷþþþþþþõӰ
|
Ʒһþ㽶߿ |
þۺϾþۺ |
þþþƷ |
ŷպ˾Ʒþþѿ |