﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-C小加</title><link>http://www.cppblog.com/cxiaojia/</link><description>厚德 博学 求真 至善
The bright moon and breeze</description><language>zh-cn</language><lastBuildDate>Sun, 19 Apr 2026 12:16:42 GMT</lastBuildDate><pubDate>Sun, 19 Apr 2026 12:16:42 GMT</pubDate><ttl>60</ttl><item><title>重新认识JavaScript</title><link>http://www.cppblog.com/cxiaojia/archive/2013/07/30/202240.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Tue, 30 Jul 2013 04:19:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/07/30/202240.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/202240.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/07/30/202240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/202240.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/202240.html</trackback:ping><description><![CDATA[&nbsp; &nbsp;JavaScrpit在我眼中一直是web前端脚本语言，而这段时间的一些工作，让我对JavaScript有了一个全新的认识。<br /><br />&nbsp;&nbsp;&nbsp;公司准备启动的一个手游项目，服务器端准备使用网易的开源框架pomelo。pomelo是基于Node.js的高性能,分布式游戏服务器框架。它包括基础的开发框架和相关的扩展组件（库和工具包），可以帮助你省去游戏开发枯燥中的重复劳动和底层逻辑的开发。 pomelo不但适用于游戏服务器开发， 也可用于开发高实时web应用，它的分布式架构可以使pomelo比普通的实时web框架扩展性更好。<br /><br />&nbsp;&nbsp;&nbsp;网易的架构师们选择了node.js作为服务器端架构的核心，说明了Node.js作为后端的Javascript运行环境一定有它自己的优越性。<br /><br />&nbsp;&nbsp;&nbsp;提到Javascript，大家首先想到的是日常使用的浏览器，现代浏览器包含了各种组件，包括渲染引擎、Javascript引擎等，其中Javascript引擎负责解释执行网页中的Javascript代码。作为Web前端最重要的语言之一，Javascript一直是前端工程师的专利。不过，Node.js是一个后端的Javascript运行环境（支持的系统包括Lnux、Windows、Mac），这意味着你可以编写系统级或者服务器端的Javascript代码，交给Node.js来解释执行。<br /><br />&nbsp;&nbsp;&nbsp;Node.js支持的语言是JavaScrpit，之所以选择JavaScrpit作为服务器端运行语言理由如下：<br /><br />&nbsp;&nbsp;&nbsp;1.Javascript作为前端工程师的主力语言，在技术社区中有相当的号召力。而且，随着Web技术的不断发展，特别是前端的重要性增加，不少前端工程师开始试水&#8221;后台应用&#8220;，在许多采用Node.js的企业中，工程师都表示因为习惯了Javascript，所以选择Node.js。<br /><br />&nbsp;&nbsp;&nbsp;2.Javascript的匿名函数和闭包特性非常适合事件驱动、异步编程，从helloworld例子中我们可以看到回调函数采用了匿名函数的形式来实现，很方便。闭包的作用则更大，看下面的代码示例：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><span style="color: #0000FF; ">var</span>&nbsp;hostRequest&nbsp;=&nbsp;http.request(requestOptions,<span style="color: #0000FF; ">function</span>(response)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;responseHTML&nbsp;='';<br />&nbsp;&nbsp;&nbsp;&nbsp;response.on('data',&nbsp;<span style="color: #0000FF; ">function</span>&nbsp;(chunk)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseHTML&nbsp;=&nbsp;responseHTML&nbsp;+&nbsp;chunk;<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;response.on('end',<span style="color: #0000FF; ">function</span>(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(responseHTML);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;do&nbsp;something&nbsp;useful</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;});<br />});</div>&nbsp; &nbsp;<span style="font-family: Arial, sans-serif; background-color: #ffffff;">在上面的代码中，我们需要在end事件中处理responseHTML变量，由于Javascript的闭包特性，我们可以在两个回调函数之外定义responseHTML变量，然后在data事件对应的回调函数中不断修改其值，并最终在end事件中访问处理。<br /></span><br />&nbsp;&nbsp;&nbsp;3.Javascript在动态语言中性能较好，有开发人员对Javacript、Python、Ruby等动态语言做了性能分析，发现Javascript的性能要好于其他语言，再加上V8引擎也是同类的佼佼者，所以Node.js的性能也受益其中。<br /><br />&nbsp;&nbsp;&nbsp;JavaScript不仅在服务器端开始流行，在游戏客户端编程方面也成为了一个很重要的选择。就在不久前，目前非常流行的一个手游引擎cocos2d-x也推出了JavaScript版本。引用创始人王哲的一句话，如果说C++最靠谱的话，那么Lua应该算是最流行，而Javascript是最有前景。<img src ="http://www.cppblog.com/cxiaojia/aggbug/202240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-07-30 12:19 <a href="http://www.cppblog.com/cxiaojia/archive/2013/07/30/202240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>由dota说游戏技能设计(转载)</title><link>http://www.cppblog.com/cxiaojia/archive/2013/05/29/200680.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Wed, 29 May 2013 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/05/29/200680.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/200680.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/05/29/200680.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/200680.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/200680.html</trackback:ping><description><![CDATA[<div>转自：<a href="http://blog.sina.com.cn/s/blog_4bb3f8270100ephf.html">http://blog.sina.com.cn/s/blog_4bb3f8270100ephf.html</a><br /></div><p><span style="color: #333333; font-family: 'Comic Sans MS';">游戏的技能设计是增加游戏可玩性的重要方式之一。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">虽然在实际工作中，大多遇到的情况应该是程序无法实现或者是因效率不够而放弃。但在一些网游以及单机游戏中，技能枯燥的现象也屡见不鲜。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">本文借鉴于DOTA的技能设计说起，探讨游戏中技能设计的思路与方向。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能可以暂时或者永远改变游戏中各种元素数值。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">这些元素几乎就是构成游戏或者角色的基本元素比如HP.MP.力量、敏捷、智力、转身速度、移动速度、视野、碰撞体积、天气、地形、等等。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">而所谓的技能就是可让玩家使用之后短暂或者永久改变这些元素的东西。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能设计的趣味性也就在此。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">一个技能所设定的元素可以直接影响玩家的心态、或者说是使用这个技能的积极性。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">如果游戏中出现几个、直到若干个无法引起玩家积极性的技能的话，那么就会影响玩家对整体游戏的积极性。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">而当我们设计技能的时候，就要从迎合玩家的心态入手来设计游戏中的技能。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">下面只是整合出我暂时所能想到的元素，排名不分优先程度。<br /></span><span style="color: #333333;">&nbsp;<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">1.视觉听觉的享受：享受？是的，就是这样。玩家在玩游戏就是一种享受的过程，满足他的需要就会让他有享受的感觉。音乐与美术特效是最直接刺激直觉听觉，影响玩家心情的元素。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">美术特效并不光是越华丽越好，重要的是一定要做到符合技能的设计。如果技能是月神剑，特效是个火焰形态的法球发出去就不太协调了。又好像是变形术，如果你使用变形术之后仅仅是改变了对方的模型大小的话，也绝对不会有那种把别人变成小动物的快感了。而伴随着华丽的特效把敌人击杀，总是会更加让人热血沸腾。这种效果当然还要配合适合的弹道以及速度。。。等等。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">音效不仅可以增加玩家的带入感，还可以给游戏增加更多的趣味性。比如玩DOTA的时候，听到有人使用疾风步的声音，而周围一个队友都没有。或者是在没有视野的地方，却可以听到有人在练野的打斗声。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">总的来说音效和音乐是最直观影响玩家心情的元素。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">2.多样性：如果每个技能都是单一伤害，或者仅仅是伤害以及常规的DEBUFF。那么也就相当于同时降低了游戏的可玩性。这里就需要组合各种元素的改变来创造出各种好玩的技能了。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">比如黑暗贤者的真空技能。就是整合了改变敌方坐标以及HP的元素、暗夜魔王可以通过改变天气来与自己的技能组合来增加自己的属性。幽鬼之刃则是在造成伤害的同时还能改变地形属性。或者是末日守卫的死亡，增加了数字判定的额外伤害。地穴编织者的缩地则是改变基础移动速度、是否可见以及碰撞之后受到伤害的整合<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">这些技能都是多样元素的重组，多改变了额外的元素，则让游戏变得更加有娱乐性。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">沙王的穿刺（自己向前穿刺，对自己移动路径中的敌人造成伤害眩晕，同时瞬间改变自己位置。点击地面施放）<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">与老虎的跳跃（向英雄模型的前方向跳跃，跳跃过后增加X范围内友方单位的攻击速度与移动速度。）<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">敌法的闪烁（点击地面施放，跳跃至该地点）<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">幻影刺客的突袭（指向性法术，点击一个目标跳跃至目标的身边，并且增加下几次攻击的攻击速度。）<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">其中都是有相同的元素，在之基础上又增加了其他元素的设定。这样即便是同类型的效果，也可以通过不同的方式实现。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">利用各种元素的组合就可以创造出各种形态各异的技能。游戏的娱乐性亦是在此。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">3.实用性与平衡性：一个音效与特效非常炫目，并且让人感觉很有意思的技能还需要一个让玩家频繁使用的要素。就是实用性。维持各个技能与英雄搭配之间的平衡，才能让技能变得有实用性。所以把实用性与平衡性放在了一起。也许你会发现一些游戏中有不具备实用性的技能，仅仅凭借着华丽的特效而存在。但这种技能也只会是一点点。。。没多少玩家愿意喜欢一个只有华而不实的技能的英雄的。击败其他玩家永远是大多数玩家最大的追求。<br /></span><span style="color: #333333;">&nbsp;<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">之后想说的一些，就是怎样通过改变游戏元素的各种组合来创造出多样性技能的思路。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">你还不知道怎样设定技能？那就再次举例。。。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">你可以把增加敌人单体移动速度、攻击速度与增加自己攻击速度、移动速度组合起来。这样就是死灵飞龙的黄泉之路了。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">你可以把矩形AOE伤害，与眩晕效果与地形改变组合。那样就变成了牛牛的沟壑。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">你可以设定一个AOE技能，对范围内的目标造成伤害，此时多加一个判定，就是对数字3的倍数的造成额外的伤害。这样就是一个AOE与末日守卫技能的组合了。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">你想增加一个RP性质极强的技能？混群骑士的C与圣骑士的T不就是么？还想更加RP一点？<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">把死亡一指的伤害X1.5，范围施放&#8212;&#8212;对范围内的随机一个敌方单位造成伤害。这样不就RP了？<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">游戏中技能的组合会更多的增加游戏的娱乐性，正是因为各种组合，所以DOTA的95个英雄都能大放光彩。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能怎样去组合？也许DOTA中技能与技能元素直接互相影响的英雄并不是非常多，但是亦都有联系。下面就来设定一个新的英雄。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">我们先定义这个英雄的定位。他是一个力量型的英雄，并且有一定的追击与逃跑能力，懂得保护自己和增加对方所受到的伤害。而他需要用怎样的技能来表现他的定位呢？<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">增加移动速度与攻击速度的技能，是最适合追击与逃跑的，但是太过单调。减免伤害与增加敌方单位受到的伤害都是已经有类似的技能了的。如何来设定一个具备这些条件而又与以往不同的英雄技能呢？<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">减免伤害的方式有多种：增加自己的护甲，或者直接减少受到伤害的具体数值，以及直接减免受到伤害的百分比等等很多方式。。。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">增加敌方受到伤害的方式亦有很多种：比如DEBUFF，让敌人受到额外的伤害，可以直接的，单次的，或者是像紫苑一样积累一定时间的。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">下面我们所想的是用怎样的技能把两种方式结合起来。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能1：增加移动与攻击速度，这个就是基础，但是不能光靠这个技能去表现。需要让其他的技能也可以实现追击与逃跑<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能2：挟持对方英雄，英雄紧贴着敌方英雄单位，无法进行攻击与移动，在这之间受到的所有伤害都会转到敌方英雄身上。这样就满足了英雄设定中所有的要求。但是这样设定有一定的问题，就是挟持之后，敌方玩家都不再攻击被挟持的单位。且挟持对友方单位的攻击并没有增幅的作用。这样的技能还是缺乏一些实用性。这样就出现了技能3.<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">技能3：永久性被动技能，减少被挟持英雄的移动速度。如果仅仅是这样的话，那么依旧并不是多样化。于是又增加了可切换的功能。姿态1是减少自己以及自己所挟持目标所受到的所有伤害，姿态2是增加自己以及自己所挟持目标的所有伤害。这样亦是通过原来DOTA没有的方式完成了减免伤害与增加对方所受到伤害的方式。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">这样一个建议的新英雄概念就出来了。。。之后就是具体设定的调整，比如被挟持的单位是处于什么状态，以及具体数值的设定等等。。。<br /></span><span style="color: #333333;">&nbsp;<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">总之，技能的设定是多样化的，多到思路永远不会被局限。永远都可以有更多更有意思的技能被设定出来。<br /></span><span style="color: #333333; font-family: 'Comic Sans MS';">此文只是写的一些技能设定的思路，没有考虑任何实现问题。。。此方面还是不要拍我了。<br /></span><span style="font-family: 'Comic Sans MS';">想写给一些苦恼与不知道怎样设定好玩的技能的新手。。。希望对他们有一点点帮助。</span></p><div></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/200680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-05-29 15:18 <a href="http://www.cppblog.com/cxiaojia/archive/2013/05/29/200680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE前摄器Proactor最好的讲解（转载）</title><link>http://www.cppblog.com/cxiaojia/archive/2013/04/12/199385.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Fri, 12 Apr 2013 09:43:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/04/12/199385.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/199385.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/04/12/199385.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/199385.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/199385.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">转自：<a href="http://blog.csdn.net/caisini_vc/article/details/4474910">http://blog.csdn.net/caisini_vc/article/details/4474910</a><br />把这两天做Proactor的一些经验和心得写一下，可能会给一些人帮助。<br />&nbsp;&nbsp;&nbsp; Proactor是异步模式的网络处理器，ACE中叫做&#8220;前摄器&#8221;。<br />&nbsp;&nbsp;&nbsp; 先讲几个概念：<br />&nbsp;&nbsp;&nbsp; 前摄器（Proactor）－异步的事件多路分离器、处理器，是核心处理类。启动后由3个线程组成（你不需要关心这三个线程，我只是让你知道一下有这回事存在）。<br />&nbsp;&nbsp;&nbsp; 接受器（Acceptor）－用于服务端，监听在一个端口上，接受用户的请求。<br />&nbsp;&nbsp;&nbsp; 连接器（Connector）－用于客户端，去连接远程的监听。当然，如果远程是ACE写的，就是Acceptor。<br />&nbsp;&nbsp;&nbsp; 异步模式－即非阻塞模式。网络的传输速度一般来讲为10Mbps、100Mbps、1000Mbps。拿千兆网来说，实际的传输速度为1000Mbps/8大概为128KB左右。我们的CPU一般为P4 3.0GHZ，如果是32位的处理器，一秒钟大概可以处理6G的字节，那么，128KB的网络速度是远远及不上处理器的速度的。网络发送数据是一位一位发送出去的，如果CPU等在这里，发送完成函数才结束，那么，处理器浪费了大量时间在网络传输上。<br />&nbsp;&nbsp;&nbsp; 操作系统提供了异步的模式来传输网络数据，工作模式即：应用程序把要发送的数据交给操作系统，操作系统把数据放在系统缓冲区后就告诉应用程序OK了，我帮你发，应用程序该干嘛干嘛去。操作系统发送完成后，会给应用系统一个回执，告诉应用程序：刚才那个包发送完成了！<br />&nbsp;&nbsp; 举个例子：你有几封邮件和包裹要发，最有效率的办法是什么？你把邮件和包裹及交给总台，总台MM说，好了，你帮你发，你忙去吧！然后你去工作了。过了一会，总台MM打电话告诉你：&#8220;刚才我叫快递公司的人来了，把你的包裹发出去了。邮局的人也来了，取走了邮件，放心好了&#8221;。同样，如果你知道今天会有包裹来，比如你在淘宝上购物了，你能成天等在总台？你应该告诉总台MM：&#8220;今天可能有我的一个快递，你帮我收一下，晚上请你肯德基！&#8221;。MM：&#8220;看在肯得基的面子上，帮你收了&#8221;。某个时间，MM打电话来了：&#8220;帅哥，你的包裹到了，我帮你签收了，快来拿吧。&#8221;<br />&nbsp;&nbsp; 因为操作系统是很有效率的，所有，他在后台收发是很快的。应用程序也很简单。Proactor就是这种异步模式的。Proactor就是总台MM；ACE_Service_Handle就是总台代为收发邮件的公司流程。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我们看一个实例：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">***********************************************************</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;TPTCPAsynchServerImpl&nbsp;:&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;ACE_Service_Handler<br />{<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;TPTCPAsynchServerImpl(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);<br />&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">TPTCPAsynchServerImpl(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);<br />&nbsp;</span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;open&nbsp;(ACE_HANDLE&nbsp;handle,&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">message_block);&nbsp;<br />&nbsp;</span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;handle_read_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Read_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result);<br />&nbsp;</span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;handle_write_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Write_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result);<br />&nbsp;</span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;handle_time_out&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Time_Value&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">tv,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">act</span><span style="color: #000000; ">=</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;initiate_read_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Read_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result);<br />&nbsp;ACE_Asynch_Read_Stream&nbsp;rs_;<br />&nbsp;ACE_Asynch_Write_Stream&nbsp;ws_;<br />};</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br />这个例子从ACE_Service_Handler继承过来，ACE_Service_Handle主要就是定义了一些回调函数。<br />1、 virtual void open (ACE_HANDLE handle, ACE_Message_Block &amp;message_block);<br />&nbsp; 当有客户端连接上来，连接建立成功后Proactor会调用这个方法。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">2、 virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &amp;result);<br />当用户要读的数据读好了后，调用这个方法</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">3、virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &amp;result);<br />当用户要写的数据在网卡上发送成功后，Proactor会回调这个方法</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">4、 virtual void&nbsp; handle_time_out (const ACE_Time_Value &amp;tv, const void *act=0);<br />当用户设定的时钟到期了，这个方法会被调用。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这跟和总台MM的联络方法是不是一样的？</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">对还缺点东西，缺少怎么向总台MM交待任务的方法。下面看看：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">首先，创建一个监听器。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;ACE_Asynch_Acceptor&lt;TPTCPAsynchServerImpl&gt; acceptor_;<br />看到没，就是我们刚才写的类，因为他继承了回调接口，并实现了自已的代码，模板中ACE_Asynch_Acceptor会在合适的时候回调这些方法。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">//创建一个地址对象<br />&nbsp;ACE_INET_Addr addr(port, ip);<br />acceptor_.open (addr, 8 * 1024, 1);<br />&nbsp;&nbsp;&nbsp; Open后，就开始监听了。其它的，向Proactor注册一些事件的事模板类中都替你做了，你不需要做很多事。<br />&nbsp;&nbsp;&nbsp; 那么，已经开始监听了，我的程序从哪里开始呢？对于一个服务程序来讲，程序是被用户的连接驱动的，一个用户程序想和通讯，必须先创建连接，就是Socket中的connect操作。这个操作Proactor会替我们做一些工作，当连接创建完成后，上面讲的Open方法会被调用，我们看看Open方法中都有些什么代码：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;TPTCPAsynchServerImpl::open&nbsp;(ACE_HANDLE&nbsp;handle,&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">message_block)<br />{<br />&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:TPTCPAsynchServerImpl::open()<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">构造读流</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(rs_.open&nbsp;(</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">,&nbsp;handle)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;ACE_ERROR&nbsp;((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">TPTCPAsynchServerImpl::open()&nbsp;Error</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">构造写流</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(ws_.open(</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">,&nbsp;handle)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;ACE_ERROR&nbsp;((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">TPTCPAsynchServerImpl::open()&nbsp;Error</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">获取客户端连接地址和端口</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;ACE_INET_Addr&nbsp;addr;&nbsp;<br />&nbsp;ACE_SOCK_SEQPACK_Association&nbsp;ass</span><span style="color: #000000; ">=</span><span style="color: #000000; ">ACE_SOCK_SEQPACK_Association(handle);&nbsp;<br />&nbsp;size_t&nbsp;addr_size</span><span style="color: #000000; ">=</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;&nbsp;<br />&nbsp;ass.get_local_addrs(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">addr,addr_size);<br />&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">server_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">onClientConnect((</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">)handle,&nbsp;addr.get_ip_address(),&nbsp;addr.get_port_number());<br /><br />&nbsp;<br /><br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果客户连接时同时提交了数据，需要伪造一个结果，然后呼叫读事件</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(message_block.length&nbsp;()&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;ACE_DEBUG((LM_DEBUG,&nbsp;"message_block.length()&nbsp;!=&nbsp;0&nbsp;"));<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;复制消息块</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">duplicate&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">message_block.duplicate&nbsp;();<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;伪造读结果，以便进行读完成回调</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;ACE_Asynch_Read_Stream_Result_Impl&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">fake_result&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_Proactor::instance&nbsp;()</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">create_asynch_read_stream_result&nbsp;(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">proxy&nbsp;(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">handle_,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duplicate,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">1024</span><span style="color: #000000; ">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_INVALID_HANDLE,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;size_t&nbsp;bytes_transferred&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;message_block.length&nbsp;();<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Accept事件处理完成，wr_ptr指针会被向前移动，将其移动到开始位置</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;duplicate.wr_ptr&nbsp;(duplicate.wr_ptr&nbsp;()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;bytes_transferred);<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这个方法将调用回调函数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;fake_result</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">complete&nbsp;(message_block.length&nbsp;(),&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;销毁伪造的读结果</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;delete&nbsp;fake_result;<br />&nbsp;}<br /><br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;否则，通知底层，准备读取用户数据<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">创建一个消息块。这个消息块将用于从套接字中异步读&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;ACE_NEW&nbsp;(mb,&nbsp;ACE_Message_Block&nbsp;(_bufSize));<br />&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(rs_.read&nbsp;(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb,&nbsp;mb</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">size&nbsp;()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;delete&nbsp;mb;<br />&nbsp;&nbsp;ACE_ERROR&nbsp;((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:open&nbsp;init&nbsp;read&nbsp;failed!</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />&nbsp;}<br />}</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我们看到，首先创建了两个流，就是前面类定义中定义的一个异步写流，一个异步读流。以后对网络的读和写就通过这两个流进行。我还给出了一段读客户端地址和端口的代码。然后是读取客户Connect可能附带的数据，那段代码不用看懂，以后使用照抄就行。然后就是</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><span style="color: #0000FF; ">if</span>&nbsp;(rs_.read&nbsp;(*mb,&nbsp;mb-&gt;size&nbsp;()&nbsp;-&nbsp;1)&nbsp;==&nbsp;-1)<br />&nbsp;{<br />&nbsp;&nbsp;delete&nbsp;mb;<br />&nbsp;&nbsp;ACE_ERROR&nbsp;((LM_ERROR,&nbsp;"%N:%l:open&nbsp;init&nbsp;read&nbsp;failed!"));<br />&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;}</div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这段代码使用读流读一段数据。这段代码就是向总台MM交待：我要收包裹，收好了叫我！<br />也就是说，这段代码99%的可能是读不出数据的，只是向Proactor注册读的事件，具体的等待、读取操作由Proactor读，读到了，就回调Handle_Read_Stream方法。ACE_Message_Block是消息块，数据就是存放在消息块中的。<br />下面看看Handle_Read_Stream方法的代码：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;TPTCPAsynchServerImpl::handle_read_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Read_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result)<br />{<br />&nbsp;result.message_block&nbsp;().rd_ptr&nbsp;()[result.bytes_transferred&nbsp;()]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">/0</span><span style="color: #000000; ">'</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">********************/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">bytes_to_read</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.bytes_to_read&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">handle</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.handle&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">bytes_transfered</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.bytes_transferred&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">act</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;(u_long)&nbsp;result.act&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">success</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.success&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">completion_key</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;(u_long)&nbsp;result.completion_key&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">error</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.error&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">********************/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;result.message_block().release();<br />&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">initiate_read_stream&nbsp;(result)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;ACE_ERROR((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:read&nbsp;stream&nbsp;failed!connection&nbsp;closed,&nbsp;remove&nbsp;it:%d/n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.handle()));<br />&nbsp;&nbsp;closeConnection(result.handle());<br />&nbsp;}&nbsp;<br />}<br />&nbsp;</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这个函数被调用，就表明有数据已经读好了，包裹已经在总台了。Proactor比总台MM还好，给你送上门了，数据就在Result里，上面演示了Result中的数据。然后把消息块释放了，然后调用initiate_read_stream继续监听网络上可能到来的数据。看看initiate_read_stream好了：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;TPTCPAsynchServerImpl::initiate_read_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Read_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result)<br />{<br />&nbsp;ACE_DEBUG((LM_TRACE,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:TPTCPAsynchServerImpl::initiate_read_stream()&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">创建一个消息块。这个消息块将用于从套接字中异步读&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ACE_Message_Block(_bufSize);<br />&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(mb&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL)<br />&nbsp;{<br />&nbsp;&nbsp;ACE_DEBUG((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:can't&nbsp;allock&nbsp;ACE_Message_Block.&nbsp;&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));&nbsp;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;}<br />&nbsp;<br />&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(rs_.read&nbsp;(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb,&nbsp;mb</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">size&nbsp;()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;delete&nbsp;mb;<br />&nbsp;&nbsp;ACE_ERROR_RETURN&nbsp;((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:rs-&gt;read()&nbsp;failed,&nbsp;clientID=%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.handle()),&nbsp;&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />&nbsp;}<br />&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">代码很简单，就是创建一个新的消息块，然后使用读流注册一个读消息就可以了。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">到此为止，Proactor的读流程很清楚了吧？</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">下面再说一个写流程。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">写流程其实更简单，在任意想向客户端写数据的地方，调用相应代码就行了，比如，我们提供了SendData方法来发送数据，在任意想发送数据的地方调用SendData就行了，SendData的代码如下：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;TPTCPAsynchServerImpl::sendData(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;clientID,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">data,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;dataLen,&nbsp;unsigned&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">id)<br />{<br />&nbsp;ACE_DEBUG((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">TPTCPAsynchServerImpl::sendData(void)&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;ACE_Message_Block&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb;&nbsp;<br />&nbsp;ACE_NEW_RETURN(mb,&nbsp;ACE_Message_Block(dataLen&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />&nbsp;mb</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">wr_ptr((</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">)data);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;ACE_OS::memcpy(mb</span><span style="color: #000000; ">-&gt;</span><span style="color: #0000FF; ">base</span><span style="color: #000000; ">(),(</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">)data,&nbsp;dataLen);<br />&nbsp;id&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GlobleSingleton::instance()</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">getIndex();<br />&nbsp;mb</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">msg_type((</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">)id);<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">向操作系统发送数据</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(connection</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">ws</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">write&nbsp;(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">mb&nbsp;,&nbsp;dataLen&nbsp;)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />&nbsp;{<br />&nbsp;&nbsp;ACE_ERROR_RETURN((LM_ERROR,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%N:%l:sendData&nbsp;failed!&nbsp;clientID=%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;clientID),</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />&nbsp;}<br />&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">简单说，就是创建了一个消息块，把用户数据拷贝进来，然后调用写流WS向Proactor发送一个Write事件就可以了，发送成功后，Handle_write_handle会被调用，看一下：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "><br />TPTCPAsynchServerImpl::handle_write_stream&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ACE_Asynch_Write_Stream::Result&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">result)<br />{<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">handle_write_stream&nbsp;called&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Reset&nbsp;pointers.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;result.message_block&nbsp;().rd_ptr&nbsp;(result.message_block&nbsp;().rd_ptr&nbsp;()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;result.bytes_transferred&nbsp;());<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">********************&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">bytes_to_write</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.bytes_to_write&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">handle</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.handle&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">bytes_transfered</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.bytes_transferred&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">act</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;(u_long)&nbsp;result.act&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">success</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.success&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">completion_key</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;(u_long)&nbsp;result.completion_key&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%d&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">error</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.error&nbsp;()));<br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">********************&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br /></span><span style="color: #0000FF; ">#if</span><span style="color: #000000; ">&nbsp;0</span><span style="color: #000000; "><br />&nbsp;&nbsp;ACE_DEBUG&nbsp;((LM_DEBUG,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%s&nbsp;=&nbsp;%s&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">message_block</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;result.message_block&nbsp;().rd_ptr&nbsp;()));<br /></span><span style="color: #0000FF; ">#endif</span><span style="color: #000000; "><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Release&nbsp;message&nbsp;block.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;result.message_block&nbsp;().release&nbsp;();<br />}</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">代码中使用了result中发数据，然后把消息块释放了，就这么简单。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br />////////////////////////////////////////////////////////////////////////////////////////////////////</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这是简单的proactor用法，当然，复杂也基本就这样用。所谓不基本的不是Proactor的内容，而是服务器编程本身的麻烦。比如说，多个连接的管理、重发机制、发送队列等等，这都不是ACE的内容。这些要大家自己思考了，并添加。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">在这里，我要说几个重要的问题：连接的管理。Acceptor是一个类，但是在每一个连接，Proactor都用了某种办法创建了一个实例，所以，连接管理的群集类一定不能在Acceptor类中，不然得到的结果就是始终只有一条记录。因为每个Acceptor都有一个实例，实例对应一个连接，群集类也就每个实例一个了。要采取的方法是一个全局的容器对象就可以了。比如我这个类：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><br />typedef&nbsp;ACE_Map_Manager&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">ACE_HANDLE,&nbsp;ConnectionBean&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">,&nbsp;ACE_Null_Mutex</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;ConnectionMap;<br />typedef&nbsp;ACE_Map_Iterator</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">ACE_HANDLE,&nbsp;ConnectionBean&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">,&nbsp;ACE_Null_Mutex</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;ConnectionIterator;<br />typedef&nbsp;ACE_Map_Entry&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">ACE_HANDLE,&nbsp;ConnectionBean&nbsp;</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">&nbsp;ConnectionEntry;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Globle<br />{<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;Globle(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);<br />&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Globle(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);<br />&nbsp;ITPServer</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;server_;<br />&nbsp;ConnectionMap&nbsp;_connections;<br />&nbsp;unsigned&nbsp;getIndex(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);&nbsp;<br />&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;getTimerId(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">);<br /></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;unsigned&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;index_;<br />&nbsp;</span><span style="color: #0000FF; ">long</span><span style="color: #000000; ">&nbsp;timerId_;<br />};<br />typedef&nbsp;ACE_Singleton</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Globle,&nbsp;ACE_Null_Mutex</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;GlobleSingleton;</span></div></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我使用ACE的Singleton模板创建这个类，每一个Acceptor要使用ConnectionMap，都使用这里的_connections，方法如下 ：<br />&nbsp; GlobleSingleton::instance()-&gt;connection.bind()......</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这个问题可是我花费了2天时间找出来的，诸位同仁不可不戒啊，给点掌声：）</p><img src ="http://www.cppblog.com/cxiaojia/aggbug/199385.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-04-12 17:43 <a href="http://www.cppblog.com/cxiaojia/archive/2013/04/12/199385.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE网络编程笔记（1）：ACE自适配通信环境</title><link>http://www.cppblog.com/cxiaojia/archive/2013/04/08/199198.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 08 Apr 2013 01:48:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/04/08/199198.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/199198.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/04/08/199198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/199198.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/199198.html</trackback:ping><description><![CDATA[<p style="font-family: Simsun; font-size: medium; line-height: normal;">介绍<br /></p><hr />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE自适配通信环境（ADAPTIVE Communication Environment）是可以自由使用、开放源码的面向对象（OO）构架（Framework），在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++Wrapper Facade（包装外观）和构架组件，可跨越多种平台完成通用的通信软件任务，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等等。<br />&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ACE的目标用户是高性能和实时通信服务和应用的开发者。它简化了使用进程间通信、事件多路分离、显式动态链接和并发的OO网络应用和服务的开发。此外，通过服务在运行时与应用的动态链接，ACE还使系统的配置和重配置得以自动化。<br /><p style="font-family: Simsun; font-size: medium; line-height: normal; text-indent: 21pt;"><br /><br />好处<br /></p><hr /><strong style="text-indent: -24px;">增强可移植性</strong>：在ACE组件的帮助下，很容易在一种OS平台上编写并发网络应用，然后快速地将它们移植到各种其他的OS平台上。而且，因为ACE是开放源码的自由软件，你无需担心被锁定在特定的操作系统平台或编译器上。<br /><strong style="text-indent: -24px;">更好的软件质量：</strong>ACE的设计使用了许多可提高软件质量的关键模式，这些质量因素包括通信软件灵活性、可扩展性、可复用性和模块性。<br /><span lang="EN-US" style="text-indent: -24px; font-family: Wingdings;"><span style="font-size: 7pt; font-family: 'Times New Roman';">&nbsp;</span></span><strong style="text-indent: -24px;">更高的效率和可预测性：</strong>ACE经仔细设计，支持广泛的应用服务质量（QoS）需求，包括延迟敏感应用的低响应等待时间、高带宽应用的高性能，以及实时应用的可预测性。<br /><strong style="text-indent: -24px;">更容易转换到标准的高级中间件：</strong>TAO使用了ACE提供的可复用组件和模式。它是CORBA的开发源码、遵循标准的实现，并为高性能和实时系统作了优化。为此，ACE和TAO被设计为能良好地协同工作，以提供全面的中间件解决方案。<br /><br /><span style="font-family: Simsun; font-size: medium; line-height: normal; text-indent: 28px;">体系结构</span><br /><hr /><br /><div style="text-align: center;"><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/Image1.gif" width="615" height="409" alt="" style="text-indent: 0px;" /></div><strong>OS适配层：</strong>ACE底层，和OS的API相关的部分。这部分ACE把不同类型的OS接口统一起来，让ACE的高层摆脱平台的依赖性。适配层增强了代码的可移植性。<br /><strong>C++包装层：</strong>ACE中间层，主要功能的实现部分。包括并发和同步、IPC、内存管理组件、定时器类、容器类、信号处理、文件系统组件和线程管理。<br /><strong>构架和模式层：</strong>ACE高层，架构和模式部分。它们的基础是若干针对特定通信软件领域的设计模式。包括事件处理、连接或服务初始化组件、流组件和服务配置组件。<br /><p>&nbsp;</p><img src ="http://www.cppblog.com/cxiaojia/aggbug/199198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-04-08 09:48 <a href="http://www.cppblog.com/cxiaojia/archive/2013/04/08/199198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE网络编程之ACE_NEW_RETURN，ACE_NEW，ACE_NEW_NORETURN</title><link>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198838.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Tue, 26 Mar 2013 07:26:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198838.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/198838.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/198838.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/198838.html</trackback:ping><description><![CDATA[ACE源码<span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">OS_Memory.h</span>是这样定义的。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;defined&nbsp;(ACE_HAS_NEW_NOTHROW)<br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;(ACE_nothrow)&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;RET_VAL;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>(ACE_nothrow)&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;<span style="color: #0000FF; ">return</span>;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW_NORETURN(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>(ACE_nothrow)&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br /><br />#&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br /><br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(ACE_bad_alloc)&nbsp;{&nbsp;ACE_del_bad_alloc&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;POINTER&nbsp;=&nbsp;0;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;RET_VAL;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br /><br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(ACE_bad_alloc)&nbsp;{&nbsp;ACE_del_bad_alloc&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;POINTER&nbsp;=&nbsp;0;&nbsp;<span style="color: #0000FF; ">return</span>;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br /><br />#&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;ACE_NEW_NORETURN(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(ACE_bad_alloc)&nbsp;{&nbsp;ACE_del_bad_alloc&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;POINTER&nbsp;=&nbsp;0;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br />#&nbsp;&nbsp;endif&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;ACE_HAS_NEW_NOTHROW&nbsp;</span><span style="color: #008000; ">*/</span><br /><br /><span style="color: #0000FF; ">#else</span>&nbsp;/*&nbsp;ACE_NEW_THROWS_EXCEPTIONS&nbsp;*/<br /><br />#&nbsp;define&nbsp;ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;RET_VAL;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br />#&nbsp;define&nbsp;ACE_NEW(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;<span style="color: #0000FF; ">return</span>;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)<br />#&nbsp;define&nbsp;ACE_NEW_NORETURN(POINTER,CONSTRUCTOR)&nbsp;\<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{&nbsp;POINTER&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CONSTRUCTOR;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(POINTER&nbsp;==&nbsp;0)&nbsp;{&nbsp;errno&nbsp;=&nbsp;ENOMEM;&nbsp;}&nbsp;\<br />&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(0)</div><br />以上是用宏定义替换的表达式，功能都是用一个POINTER指针new一个CONSTRUCTOR实例，内部做了一些错误信息的标志和异常处理。<br />宏ifelse对平台的不同进行了分离，每个平台下都有三种new的方法，他们的区别是return。<br />每个宏定义都用到了do{}while(0)，是因为宏只能替换一句表达式，而你用do{}while(0)可以方便的把多个表达式集中起来。<img src ="http://www.cppblog.com/cxiaojia/aggbug/198838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-03-26 15:26 <a href="http://www.cppblog.com/cxiaojia/archive/2013/03/26/198838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket阻塞与非阻塞，同步与异步、I/O模型(转)</title><link>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198831.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Tue, 26 Mar 2013 05:36:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198831.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/198831.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/03/26/198831.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/198831.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/198831.html</trackback:ping><description><![CDATA[<h2><p bk-sidecatalog-title"="" style="margin: 0px 0px 10px; padding: 0px 0px 6px; border-bottom-color: #dedfe1; border-bottom-width: 1px; border-bottom-style: solid; clear: both;"><span style="margin: 0px; padding: 0px; color: #336699;"><span style="margin: 0px; padding: 0px; line-height: 36px; font-size: 22px;">转自：<a href="http://blog.csdn.net/hguisu/article/details/7453390">http://blog.csdn.net/hguisu/article/details/7453390</a><br /><br /><br />1. 概念理解</span></span></p></h2><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="padding: 0px; color: #333333; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;">&nbsp; &nbsp; &nbsp;在进行网络编程时，我们常常见到<span style="margin: 0px; padding: 0px; font-family: Arial, Helvetica, sans-serif, 宋体; font-size: 12px; line-height: 16px; text-indent: 24px;">同步(Sync)/异步(Async)，阻塞(Block)/非阻塞(Unblock)</span>四种调用方式：</span><span style="margin: 0px; padding: 0px; font-family: Verdana; font-size: 10.5pt; line-height: 21px;"><br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">同步：</span></strong></span><span style="margin: 0px; padding: 0px; font-family: Verdana; font-size: 10.5pt; line-height: 21px;"><br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; line-height: 21px;"><span style="margin: 0px; padding: 0px; font-size: 10.5pt;">所谓同步，就是在发出一个功能调用时，在没有得到结果之前，该调用就不返回。</span><span style="margin: 0px; padding: 0px; font-size: 12px;"><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #666666; text-indent: 32px; line-height: 24px;"><strong style="margin: 0px; padding: 0px;">也就是必须一件一件事做</strong></span><span style="margin: 0px; padding: 0px; font-family: 宋体, Arial; color: #666666; line-height: 18px; text-indent: 32px;"><span style="margin: 0px; padding: 0px; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">,</span></span><span style="margin: 0px; padding: 0px; font-family: 宋体; line-height: 24px;">等前一件做完了才能做下一件事。</span></span></span></span></span></p><p style="padding: 0px; color: #333333; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 21px;"><span style="margin: 0px; padding: 0px; font-size: 12px;"><span style="margin: 0px; padding: 0px; font-family: 宋体, Arial; color: #666666; line-height: 18px; text-indent: 32px;"></span></span></span></span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; color: #666666;">例如普通<span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">B/S</span>模式（同步）：提交请求<span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">-&gt;</span>等待服务器处理<span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">-&gt;</span>处理完毕返回&nbsp;这个期间客户端浏览器不能干任何事</p><p style="padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; font-size: 12px; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 21px; font-size: 10.5pt;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">异步：</span></strong></span><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;"><br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 21px; font-size: 10.5pt;">异步的概念和同步相对。当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者。</span></span></p><p style="padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 21px;"><span style="margin: 0px; padding: 0px; font-size: 10.5pt;">&nbsp; &nbsp; &nbsp;</span><span style="margin: 0px; padding: 0px; font-family: 宋体; font-size: 12px; color: #666666; line-height: 24px; text-indent: 32px;">例如 ajax请求（</span><span style="margin: 0px; padding: 0px; font-size: 12px;"><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #666666; text-indent: 32px; line-height: 24px;">异步）</span><span style="margin: 0px; padding: 0px; font-family: 宋体, Arial; color: #666666; text-indent: 32px; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">:&nbsp;</span></span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #666666; text-indent: 32px; line-height: 24px;">请求通过事件触发</span><span style="margin: 0px; padding: 0px; font-family: 宋体, Arial; color: #666666; text-indent: 32px; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">-&gt;</span></span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #666666; text-indent: 32px; line-height: 24px;">服务器处理（这是浏览器仍然可以作其他事情）</span><span style="margin: 0px; padding: 0px; font-family: 宋体, Arial; color: #666666; text-indent: 32px; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: 'Times New Roman';">-&gt;</span></span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #666666; text-indent: 32px; line-height: 24px;">处理完毕</span></span></span></span></p><p style="padding: 0px; color: #333333; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;">阻塞</strong></span></span><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;"><br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">阻塞调用是指调用结果返回之前，当前线程会被挂起（线程进入非可执行状态，在这个状态下，cpu不会给线程分配时间片，即线程暂停运行）。函数只有在得到结果之后才会返回。</span></span></p><p style="padding: 0px; color: #333333; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">&nbsp; &nbsp; &nbsp;有人也许会把阻塞调用和同步调用等同起来，实际上他是不同的。对于同</span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">步调用来说，很多时候当前线程还是激活的，只是从逻辑上当前函数没有返回而已。</span><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;">&nbsp;例如，我们在s</span><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;">ocket</span></span><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;">中调用r</span><span style="margin: 0px; padding: 0px; font-family: Verdana; font-size: 10.5pt; line-height: 21px;">ecv</span><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;">函数，如果缓冲区中没有数</span><span style="margin: 0px; padding: 0px; font-size: 10.5pt; line-height: 21px;">据，这个函数就会一直等待，直到有数据才返回。而此时，当前线程还会继续处理各种各样的消息。</span></span></p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;">非阻塞</strong></span></span><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;"><br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">非阻塞和阻塞的概念相对应，指在不能立刻得到结果之前，该函数不会阻塞当前线程，而会立刻返回。</span><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;"><br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">对象的阻塞模式和阻塞函数调用</span><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;"><br style="margin: 0px; padding: 0px;" /></span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性，但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式，我们可以通过一定的</span><span style="margin: 0px; padding: 0px; line-height: 18px;"><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;">API</span></span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">去轮询状</span>&nbsp;<span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">态，在适当的时候调用阻塞函数，就可以避免阻塞。而对于非阻塞对象，调用特殊的函数也可以进入阻塞调用。函数</span><span style="margin: 0px; padding: 0px; line-height: 18px;"><span style="margin: 0px; padding: 0px; font-family: Verdana; line-height: 21px; font-size: 10.5pt;">select</span></span><span style="margin: 0px; padding: 0px; line-height: 21px; font-size: 10.5pt;">就是这样的一个例子。</span></span></p><p style="padding: 0px; color: #333333; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">&nbsp;</p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">1. 同步，就是我调用一个功能，该功能没有结束前，我死等结果。</span><br style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;" /><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">2. 异步，就是<span style="margin: 0px; padding: 0px; line-height: 20px;">我调用一个功能，</span>不需要知道该功能结果，该功能有结果后通知我（回调通知）</span><br style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;" /><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">3. 阻塞， &nbsp; &nbsp; &nbsp;就是调用我（函数），我<span style="margin: 0px; padding: 0px; line-height: 20px;">（函数）</span>没有接收完数据或者没有得到结果之前，我不会返回。</span><br style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;" /><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">4. 非阻塞， &nbsp;就是调用我<span style="margin: 0px; padding: 0px; line-height: 20px;">（函数）</span>，我<span style="margin: 0px; padding: 0px; line-height: 20px;">（函数）</span>立即返回，<span style="margin: 0px; padding: 0px; line-height: 20px;">通过select通知调用者</span></span></span></p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"></span></p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">同步IO和异步IO的区别就在于：<span style="margin: 0px; padding: 0px; color: #ff0000;">数据拷贝的时候进程是否阻塞！</span></p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; color: #000000;">阻塞IO和非阻塞IO的区别就在于：</span><span style="margin: 0px; padding: 0px; color: #ff0000;">应用程序的调用是否立即返回！</span></p><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">对于举个简单c/s 模式：</span></span></p><p style="padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; font-size: 12px;"></p><div style="margin: 0px; color: #333333; font-family: Arial; background-color: #ffffff;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #ff0000;">同步：</span>提交请求-&gt;等待服务器处理-&gt;处理完毕返回这个期间客户端浏览器不能干任何事<br style="margin: 0px; padding: 0px;" /><span style="margin: 0px; padding: 0px; color: #ff0000;">异步：</span>请求通过事件触发-&gt;服务器处理（这是浏览器仍然可以作其他事情）-&gt;处理完毕</span></div><div style="margin: 0px; color: #333333; font-family: Arial; background-color: #ffffff;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: Helvetica, Arial, sans-serif; font-size: 12px; line-height: 19px;">同步和异步都只针对于本机SOCKET而言的。</span><br style="margin: 0px; padding: 0px;" /></span></div><div style="margin: 0px; color: #333333; font-family: Arial; background-color: #ffffff;"><p style="padding: 0px; line-height: 25px;"><span style="margin: 0px; padding: 0px;">同步和异步,阻塞和非阻塞,有些混用,其实它们完全不是一回事,而且它们修饰的对象也不相同。<br style="margin: 0px; padding: 0px;" />阻塞和非阻塞是指当进程访问的数据如果尚未就绪,进程是否需要等待,</span><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">简单说这相当于函数内部的实现区别</span><span style="margin: 0px; padding: 0px;">,也就是未就绪时是直接返回还是等待就绪;</span></p><p style="padding: 0px; line-height: 25px;"><span style="margin: 0px; padding: 0px;">而同步和异步是</span><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">指访问数据的机制</span><span style="margin: 0px; padding: 0px;">,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就绪与读写二个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待"通知")</span></p></div><h2><a name="t1" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><p bk-sidecatalog-title"="" style="margin: 0px 0px 10px; padding: 0px 0px 6px; border-bottom-color: #dedfe1; border-bottom-width: 1px; border-bottom-style: solid; clear: both;"><span style="margin: 0px; padding: 0px; color: #336699;"><span style="margin: 0px; padding: 0px; line-height: 36px; font-size: 22px;">1. Linux下的五种I/O模型</span></span></p></h2><div style="margin: 0px; color: #333333; font-family: Arial; background-color: #ffffff;"><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;">1)阻塞I/O（blocking I/O）<br style="margin: 0px; padding: 0px;" />2)非阻塞I/O&nbsp;<span style="margin: 0px; padding: 0px;">（nonblocking I/O）</span><br style="margin: 0px; padding: 0px;" />3) I/O复用(select 和poll)&nbsp;<span style="margin: 0px; padding: 0px;">（I/O multiplexing）</span><br style="margin: 0px; padding: 0px;" />4)信号驱动I/O&nbsp;<span style="margin: 0px; padding: 0px;">（signal driven I/O (SIGIO)）</span><br style="margin: 0px; padding: 0px;" />5)异步I/O&nbsp;<span style="margin: 0px; padding: 0px;">（asynchronous I/O (the POSIX aio_functions)）</span><br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"></p><p style="margin: 0px; padding: 0px;">前四种都是同步，只有最后一种才是异步IO。</p><br style="margin: 0px; padding: 0px;" /><h3><a name="t2" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; color: #3333ff; line-height: 24px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 14px;">阻塞I/O模型：</span></strong></span></span></h3><p style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffcc00;">简介：进程会</span><span style="margin: 0px; padding: 0px; color: #ff0000; background-color: #ffcc00;">一直阻塞</span><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">，直到数据拷贝完成</span><br style="margin: 0px; padding: 0px;" /></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: tahoma, 宋体; line-height: 22px;">&nbsp;&nbsp;&nbsp;&nbsp; 应用程序调用一个IO函数，导致应用程序阻塞，等待数据准备好。 如果数据没有准备好，一直等待&#8230;.数据准备好了，从内核拷贝到用户空间,IO函数返回成功指示。</span></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #ff6600;">阻塞I/O模型图：</span></strong><span style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;">在调用recv()/recvfrom（）函数时，发生在内核中等待数据和复制数据的过程。</span></span></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><img src="http://my.csdn.net/uploads/201204/12/1334216532_9745.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /><br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;">&nbsp; &nbsp; 当调用recv()函数时，系统首先查是否有准备好的数据。如果数据没有准备好，那么系统就处于等待状态。当数据准备好后，将数据从系统缓冲区复制到用户空间，然后该函数返回。在套接应用程序中，当调用recv()函数时，未必用户空间就已经存在数据，那么此时recv()函数就会处于等待状态。<br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px 0px 15px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp;当使用socket()函数和WSASocket()函数创建套接字时，默认的套接字都是阻塞的。这意味着当调用Windows Sockets API不能立即完成时，线程处于等待状态，直到操作完成。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; 并不是所有Windows Sockets API以阻塞套接字为参数调用都会发生阻塞。例如，以阻塞模式的套接字为参数调用bind()、listen()函数时，函数会立即返回。将可能阻塞套接字的Windows Sockets API调用分为以下四种:</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; 1．输入操作：&nbsp;recv()、recvfrom()、WSARecv()和WSARecvfrom()函数。以阻塞套接字为参数调用该函数接收数据。如果此时套接字缓冲区内没有数据可读，则调用线程在数据到来前一直睡眠。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; 2．输出操作：&nbsp;send()、sendto()、WSASend()和WSASendto()函数。以阻塞套接字为参数调用该函数发送数据。如果套接字缓冲区没有可用空间，线程会一直睡眠，直到有空间。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; 3．接受连接：accept()和WSAAcept()函数。以阻塞套接字为参数调用该函数，等待接受对方的连接请求。如果此时没有连接请求，线程就会进入睡眠状态。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp;4．外出连接：connect()和WSAConnect()函数。对于TCP连接，客户端以阻塞套接字为参数，调用该函数向服务器发起连接。该函数在收到服务器的应答前，不会返回。这意味着TCP连接总会等待至少到服务器的一次往返时间。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">　　使用阻塞模式的套接字，开发网络程序比较简单，容易实现。当希望能够立即发送和接收数据，且处理的套接字数量比较少的情况下，使用阻塞模式来开发网络程序比较合适。</span></p><p style="margin: 10px 0px; padding: 0px; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp; 阻塞模式套接字的不足表现为，在大量建立好的套接字线程之间进行通信时比较困难。当使用&#8220;生产者-消费者&#8221;模型开发网络程序时，为每个套接字都分别分配一个读线程、一个处理数据线程和一个用于同步的事件，那么这样无疑加大系统的开销。其最大的缺点是当希望同时处理大量套接字时，将无从下手，其扩展性很差</span></p><h3><a name="t3" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; color: #3333ff; line-height: 24px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 14px;">非阻塞IO模型</span></strong></span></span>&nbsp;</h3></div><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div style="margin: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffcc00;">简介：非阻塞IO通过进程反复调用IO函数（</span><span style="margin: 0px; padding: 0px; color: #ff0000; background-color: #ffcc00;">多次系统调用，并马上返回</span><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">）；</span><span style="margin: 0px; padding: 0px; color: #ff0000; background-color: #ffcc00;">在数据拷贝的过程中，进程是阻塞的</span><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">；</span></div><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们把一个SOCKET接口设置为非阻塞就是告诉内核，当所请求的I/O操作无法完成时，不要将进程睡眠，而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好，如果没有准备好，继续测试，直到数据准备好为止。在这个不断测试的过程中，会大量的占用CPU的时间。</span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;">&nbsp; &nbsp; 把<span style="margin: 0px; padding: 0px; font-size: 14px;">SOCKET</span>设置为非阻塞模式，即通知系统内核：在调用Windows Sockets API时，不要让线程睡眠，而应该让函数立即返回。在返回时，该函数返回一个错误代码。图所示，一个非阻塞模式套接字多次调用recv()函数的过程。前三次调用recv()函数时，内核数据还没有准备好。因此，该函数立即返回WSAEWOULDBLOCK错误代码。第四次调用recv()函数时，数据已经准备好，被复制到应用程序的缓冲区中，recv()函数返回成功指示，应用程序开始处理数据。</span><br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><img src="http://my.csdn.net/uploads/201204/12/1334216607_3004.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /><br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;">&nbsp; &nbsp; &nbsp;当使用socket()函数和WSASocket()函数创建套接字时，默认都是阻塞的。在创建套接字之后，通过调用ioctlsocket()函数，将该套接字设置为非阻塞模式。Linux下的函数是:fcntl().</span><br style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;" /><span style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;">&nbsp;&nbsp;&nbsp; 套接字设置为非阻塞模式后，在调用Windows Sockets API函数时，调用函数会立即返回。大多数情况下，这些函数调用都会调用&#8220;失败&#8221;，并返回WSAEWOULDBLOCK错误代码。说明请求的操作在调用期间内没有时间完成。通常，应用程序需要重复调用该函数，直到获得成功返回代码。</span><br style="margin: 0px; padding: 0px; font-family: Simsun; font-size: 16px;" /></span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp; 需要说明的是并非所有的Windows Sockets API在非阻塞模式下调用，都会返回WSAEWOULDBLOCK错误。例如，以非阻塞模式的套接字为参数调用bind()函数时，就不会返回该错误代码。当然，在调用WSAStartup()函数时更不会返回该错误代码，因为该函数是应用程序第一调用的函数，当然不会返回这样的错误代码。</span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp; 要将套接字设置为非阻塞模式，除了使用ioctlsocket()函数之外，还可以使用WSAAsyncselect()和WSAEventselect()函数。当调用该函数时，套接字会自动地设置为非阻塞方式。<br style="margin: 0px; padding: 0px;" /></span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">　　由于使用非阻塞套接字在调用函数时，会经常返回WSAEWOULDBLOCK错误。所以在任何时候，都应仔细检查返回代码并作好对&#8220;失败&#8221;的准备。应用程序连续不断地调用这个函数，直到它返回成功指示为止。上面的程序清单中，在While循环体内不断地调用recv()函数，以读入1024个字节的数据。这种做法很浪费系统资源。</span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp; 要完成这样的操作，有人使用MSG_PEEK标志调用recv()函数查看缓冲区中是否有数据可读。同样，这种方法也不好。因为该做法对系统造成的开销是很大的，并且应用程序至少要调用recv()函数两次，才能实际地读入数据。较好的做法是，使用套接字的&#8220;I/O模型&#8221;来判断非阻塞套接字是否可读可写。</span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp; 非阻塞模式套接字与阻塞模式套接字相比，不容易使用。使用非阻塞模式套接字，需要编写更多的代码，以便在每个Windows Sockets API函数调用中，对收到的WSAEWOULDBLOCK错误进行处理。因此，非阻塞套接字便显得有些难于使用。</span></p><p style="margin: 10px 0px; padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: Simsun; font-size: 16px;"><span style="margin: 0px; padding: 0px;">&nbsp;&nbsp;&nbsp; 但是，非阻塞套接字在控制建立的多个连接，在数据的收发量不均，时间不定时，明显具有优势。这种套接字在使用上存在一定难度，但只要排除了这些困难，它在功能上还是非常强大的。通常情况下，可考虑使用套接字的&#8220;I/O模型&#8221;，它有助于应用程序通过异步方式，同时对一个或多个套接字的通信加以管理。</span></p><span style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br style="margin: 0px; padding: 0px;" /></span><h3><a name="t4" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><span style="margin: 0px; padding: 0px; font-size: 14px;">IO复用模型：</span></span></strong></span></h3><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px;">&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffcc00;">&nbsp;简介：主要是select和epoll；对一个IO端口，两次调用，两次返回，比阻塞IO并没有什么优越性；关键是能实现同时对多个IO端口进行监听；</span></span><br style="margin: 0px; padding: 0px;" /></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">&nbsp; &nbsp;</span><span style="margin: 0px; padding: 0px;">&nbsp; &nbsp;I/O复用模型会用到select、poll、epoll函数，这几个函数也会使进程阻塞，但是和阻塞I/O所不同的的，这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作，多个写操作的I/O函数进行检测，直到有数据可读或可写时，才真正调用I/O操作函数</span><span style="margin: 0px; padding: 0px; color: #3333ff;">。</span></span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px;"><img src="http://my.csdn.net/uploads/201204/12/1334216620_6310.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /></span><br style="margin: 0px; padding: 0px;" /></span></p><h3><a name="t5" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 14px;">信号驱动IO</span></strong></span></span></h3><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffcc00;">简介：<span style="margin: 0px; padding: 0px;">两次调用，两次返回；</span></span><br style="margin: 0px; padding: 0px;" /></span></span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px;">首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数，进程继续运行并不阻塞。当数据准备好时，进程会收到一个SIGIO信号，可以在信号处理函数中调用I/O操作函数处理数据。</span></span></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px;"><img src="http://my.csdn.net/uploads/201204/12/1334216632_6025.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /></span><br style="margin: 0px; padding: 0px;" /></span></p><h3><a name="t6" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><span style="margin: 0px; padding: 0px; font-size: 14px;">异步IO模型</span></span></strong></span></h3><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; background-color: #ffcc00;">&nbsp; 简介：数据拷贝的时候进程无需阻塞。</span></span><br style="margin: 0px; padding: 0px;" /></p><p style="margin: 0px 0px 15px; padding: 0px; color: #333333; background-color: #ffffff; font-family: 微软雅黑, Verdana, sans-serif, 宋体; line-height: 24px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp;</strong></span><span style="margin: 0px; padding: 0px;">当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者的输入输出操作</span></span></p><span style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 21px;"><img src="http://my.csdn.net/uploads/201204/12/1334216641_7821.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /></span></span><br style="margin: 0px; padding: 0px;" /></span><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;">同步IO引起进程阻塞，直至IO操作完成。<br style="margin: 0px; padding: 0px;" />异步IO不会引起进程阻塞。<br style="margin: 0px; padding: 0px;" />IO复用是先通过select调用阻塞。<br style="margin: 0px; padding: 0px;" /></span></span></p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;"><br style="margin: 0px; padding: 0px;" /></span></span></p><h3><a name="t7" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; line-height: 21px;"><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 14px;">5个I/O模型的比较：</span></strong></span></span></span></h3><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;"><img src="http://my.csdn.net/uploads/201204/12/1334216724_2405.jpg" alt="" style="margin: 0px; padding: 0px; border: none;" /><br style="margin: 0px; padding: 0px;" /></span></span></p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14px; line-height: 21px;"><br style="margin: 0px; padding: 0px;" /></span></span></p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"></span></p><h2><a name="t8" style="margin: 0px; padding: 0px; color: rgb(51, 102, 153);"></a><p bk-sidecatalog-title"="" style="margin: 0px 0px 10px; padding: 0px 0px 6px; border-bottom-color: #dedfe1; border-bottom-width: 1px; border-bottom-style: solid; clear: both;"><span style="margin: 0px; padding: 0px; color: #336699;"><span style="margin: 0px; padding: 0px; line-height: 36px; font-size: 22px;">1. select、poll、epoll简介<br style="margin: 0px; padding: 0px;" /></span></span></p></h2><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">epoll跟select都能提供多路I/O复用的解决方案。在现在的Linux内核里有都能够支持，其中epoll是Linux所特有，而select则应该是POSIX所规定，一般操作系统均有实现</p><p style="padding: 0px; color: #333333; line-height: 26px; background-color: #ffffff; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; font-size: 12px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"></span></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; font-family: Arial; line-height: 21px;">select：</span></span></strong></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是：</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">1、 单个进程可监视的fd数量被限制，即能监听端口的大小有限。<br style="margin: 0px; padding: 0px;" /></p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般来说这个数目和系统内存关系很大，具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048.</p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">2、 对socket进行扫描时是线性扫描，即采用轮询的方法，效率较低：<br style="margin: 0px; padding: 0px;" /></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当套接字比较多的时候，每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数，当他们活跃时，自动完成相关操作，那就避免了轮询，这正是epoll与kqueue做的。</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">3、需要维护一个用来存放大量fd的数据结构，这样会使得用户空间和内核空间在传递该结构时复制开销大</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; line-height: 21px;">poll：</span></span></strong></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; line-height: 21px;"></span></span>poll本质上和select没有区别，它将用户传入的数组拷贝到内核空间，然后查询每个fd对应的设备状态，如果设备就绪则在设备等待队列中加入一项并继续遍历，如果遍历完所有fd后没有发现就绪设备，则挂起当前进程，直到设备就绪或者主动超时，被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">它没有最大连接数的限制，原因是它是基于链表来存储的，但是同样有一个缺点：</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">1、大量的fd的数组被整体复制于用户态和内核地址空间之间，而不管这样的复制是不是有意义。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、poll还有一个特点是&#8220;水平触发&#8221;，如果报告了fd后，没有被处理，那么下次poll时会再次报告该fd。</p><strong style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; line-height: 20px;"><span style="margin: 0px; padding: 0px; line-height: 21px;">epoll:</span></span></strong><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;">epoll支持水平触发和边缘触发，最大的特点在于边缘触发，它只告诉进程哪些fd刚刚变为就需态，并且只会通知一次。还有一个特点是，epoll使用&#8220;事件&#8221;的就绪通知方式，通过epoll_ctl注册fd，一旦该fd就绪，内核就会采用类似callback的回调机制来激活该fd，epoll_wait便可以收到通知<br style="margin: 0px; padding: 0px;" /></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;"><span style="margin: 0px; padding: 0px; color: #000000; background-color: #ffcc00;">epoll的优点：</span><br style="margin: 0px; padding: 0px;" /></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; font-family: Arial; background-color: #ffffff; line-height: 1.8;"></p><div style="margin: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">1、没有最大并发连接的限制，</span></strong>能打开的FD的上限远大于1024（1G的内存上能监听约10万个端口）；<br style="margin: 0px; padding: 0px;" /><span style="margin: 0px; padding: 0px; color: #3333ff;"><strong style="margin: 0px; padding: 0px;">2、效率提升</strong></span>，不是轮询的方式，不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数；<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="margin: 0px; padding: 0px; background-color: #ffcc00;">&nbsp;即Epoll最大的优点就在于它只管你&#8220;活跃&#8221;的连接，而跟连接总数无关，因此在实际的网络环境中，Epoll的效率就会远远高于select和poll。</span></div><div style="margin: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #3333ff;">3、&nbsp;内存拷贝</span></strong>，利用mmap()文件映射内存加速与内核空间的消息传递；即epoll使用mmap减少复制开销。<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" /><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 18px;">select、poll、epoll 区别总结：</span></strong></div><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">1、支持一个进程所能打开的最大连接数</p><table border="1" cellpadding="0" cellspacing="0" style="margin: 0px; padding: 0px; color: #333333; font-size: 14px; border-style: solid; border-color: #c0c0c0; line-height: 25px; background-color: #ffffff; border-collapse: collapse; font-family: Georgia, 'Times new roman', Times, san-serif;"><tbody style="margin: 0px; padding: 0px;"><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">select</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">单个进程所能打开的最大连接数有FD_SETSIZE宏定义，其大小是32个整数的大小（在32位的机器上，大小就是32*32，同理64位机器上FD_SETSIZE为32*64），当然我们可以对进行修改，然后重新编译内核，但是性能可能会受到影响，这需要进一步的测试。</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">poll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">poll本质上和select没有区别，但是它没有最大连接数的限制，原因是它是基于链表来存储的</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">epoll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">虽然连接数有上限，但是很大，1G内存的机器上可以打开10万左右的连接，2G内存的机器可以打开20万左右的连接</p></td></tr></tbody></table><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">2、FD剧增后带来的IO效率问题</p><table border="1" cellpadding="0" cellspacing="0" style="margin: 0px; padding: 0px; color: #333333; font-size: 14px; border-style: solid; border-color: #c0c0c0; line-height: 25px; background-color: #ffffff; border-collapse: collapse; font-family: Georgia, 'Times new roman', Times, san-serif;"><tbody style="margin: 0px; padding: 0px;"><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">select</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">因为每次调用时都会对连接进行线性遍历，所以随着FD的增加会造成遍历速度慢的&#8220;线性下降性能问题&#8221;。</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">poll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">同上</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">epoll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">因为epoll内核中实现是根据每个fd上的callback函数来实现的，只有活跃的socket才会主动调用callback，所以在活跃socket较少的情况下，使用epoll没有前面两者的线性下降的性能问题，但是所有socket都很活跃的情况下，可能会有性能问题。</p></td></tr></tbody></table><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">3、 消息传递方式</p><table border="1" cellpadding="0" cellspacing="0" style="margin: 0px; padding: 0px; color: #333333; font-size: 14px; border-style: solid; border-color: #c0c0c0; line-height: 25px; background-color: #ffffff; border-collapse: collapse; font-family: Georgia, 'Times new roman', Times, san-serif;"><tbody style="margin: 0px; padding: 0px;"><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">select</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">内核需要将消息传递到用户空间，都需要内核拷贝动作</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">poll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">同上</p></td></tr><tr style="margin: 0px; padding: 0px;"><td width="111" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">epoll</p></td><td width="457" style="margin: 0px; padding: 3px; border-style: solid; border-color: #c0c0c0; border-collapse: collapse;"><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; line-height: 1.8;">epoll通过内核和用户空间共享一块内存来实现的。</p></td></tr></tbody></table><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #ff0000;">总结：</span></strong><br style="margin: 0px; padding: 0px;" /></p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">综上，在选择select，poll，epoll时要根据具体的使用场合以及这三种方式的自身特点。</p><p style="margin-top: 12px; margin-bottom: 12px; padding: 0px; color: #333333; line-height: 25px; background-color: #ffffff; font-family: Georgia, 'Times new roman', Times, san-serif;">1、表面上看epoll的性能最好，但是在连接数少并且连接都十分活跃的情况下，select和poll的性能可能比epoll好，毕竟epoll的通知机制需要很多函数回调。</p><p style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">2、<span style="margin: 0px; padding: 0px; color: #000000; background-color: #ffcc00;">select低效是因为每次它都需要轮询。但低效也是相对的，视情况而定，也可通过良好的设计改善</span></p><img src ="http://www.cppblog.com/cxiaojia/aggbug/198831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-03-26 13:36 <a href="http://www.cppblog.com/cxiaojia/archive/2013/03/26/198831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>#pragma once 与 #ifndef 解析(转)</title><link>http://www.cppblog.com/cxiaojia/archive/2013/03/18/198526.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 18 Mar 2013 02:28:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/03/18/198526.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/198526.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/03/18/198526.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/198526.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/198526.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">转自：</span><a href="http://blog.csdn.net/slimfox/article/details/1565950">http://blog.csdn.net/slimfox/article/details/1565950</a><br /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;<br /><br />为了避免同一个文件被include多次，C/C++中有两种方式，一种是#ifndef方式，一种是#pragma once方式。在能够支持这两种方式的编译器上，二者并没有太大的区别，但是两者仍然还是有一些细微的区别。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; 方式一：</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; display: block; background-color: #e0e0ff; border: 1px solid #b0b0f0;"><span style="margin: 0px; padding: 0px; font-family: 'courier new', courier;">&nbsp;&nbsp;&nbsp; #ifndef __SOMEFILE_H__<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; #define __SOMEFILE_H__<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; ... ... // 一些声明语句<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; #endif</span></span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; 方式二：</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; display: block; background-color: #e0e0ff; border: 1px solid #b0b0f0;"><span style="margin: 0px; padding: 0px; font-family: 'courier new', courier;">&nbsp;&nbsp;&nbsp; #pragma once<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; ... ... // 一些声明语句</span></span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; #ifndef的方式依赖于宏名字不能冲突，这不光可以保证同一个文件不会被包含多次，也能保证内容完全相同的两个文件不会被不小心同时包含。当然，缺点就是如果不同头文件的宏名不小心&#8220;撞车&#8221;，可能就会导致头文件明明存在，编译器却硬说找不到声明的状况&#8212;&#8212;这种情况有时非常让人抓狂。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; #pragma once则由编译器提供保证：同一个文件不会被包含多次。注意这里所说的&#8220;同一个文件&#8221;是指物理上的一个文件，而不是指内容相同的两个文件。带来的好处是，你不必再费劲想个宏名了，当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝，本方法不能保证他们不被重复包含。当然，相比宏名碰撞引发的&#8220;找不到声明&#8221;的问题，重复包含更容易被发现并修正。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; #pragma once方式产生于#ifndef之后，因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受语言天生的支持，不受编译器的任何限制；而#pragma once方式却不受一些较老版本的编译器支持，换言之，它的兼容性不够好。也许，再过几年等旧的编译器死绝了，这就不是什么问题了。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; 我还看到一种用法是把两者放在一起的：</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; display: block; background-color: #e0e0ff; border: 1px solid #b0b0f0;"><span style="margin: 0px; padding: 0px; font-family: 'courier new', courier;">&nbsp;&nbsp;&nbsp; #pragma once<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; #ifndef __SOMEFILE_H__<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; #define __SOMEFILE_H__<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; ... ... // 一些声明语句<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; #endif</span></span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; 看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险，所以混用两种方法似乎不能带来更多的好处，倒是会让一些不熟悉的人感到困惑。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; 选择哪种方式，应该在了解两种方式的情况下，视具体情况而定。事实上，只要有一个合理的约定来避开缺点，我认为哪种方式都是可以接受的。而这个已经不是标准或者编译器的责任了，应当由程序员来搞定。</span><br style="margin: 0px; padding: 0px; color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; btw：我看到GNU的一些讨论似乎是打算在GCC 3.4（及其以后？）的版本取消对#pragma once的支持。不过我手上GCC 3.4.2和GCC 4.1.1仍然支持#pragma once，甚至没有deprecation warning。VC6及其以后版本亦提供对#pragma once方式的支持。看来这一特性已经稳定下来了。&nbsp;</span><img src ="http://www.cppblog.com/cxiaojia/aggbug/198526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-03-18 10:28 <a href="http://www.cppblog.com/cxiaojia/archive/2013/03/18/198526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC文档序列化实现保存和加载 </title><link>http://www.cppblog.com/cxiaojia/archive/2013/03/02/198177.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 02 Mar 2013 10:04:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2013/03/02/198177.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/198177.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2013/03/02/198177.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/198177.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/198177.html</trackback:ping><description><![CDATA[<p class="p0"><strong>1<span style="font-family: 宋体">、序列化定义</span></strong></p>
<p class="p0">MFC<span style="font-family: 宋体">文档</span><span style="font-family: 'Times New Roman'">-</span><span style="font-family: 宋体">视图结构中，序列化机制可以实现内存中对象储存和加载。</span></p>
<p class="p0">序列化机制分为序列化和反序列化，序列化是把内存中的对象以二进制文件的形式存储在磁盘中。反序列化是把序列化后生成的文件恢复到内存。</p>
<p class="p0"><strong>2<span style="font-family: 宋体">、</span><span style="font-family: 'Times New Roman'">CArchive</span><span style="font-family: 宋体">类</span></strong></p>
<p class="p0">CArchive<span style="font-family: 宋体">没有基类。</span><br />CArchive<span style="font-family: 宋体">允许以一个永久二进制（通常为磁盘存储）的形式保存一个对象的复杂网络，它可以在对象被删除时，还能永久保存。可以从永久存储中装载对象，在内存中重新构造它们。使得数据永久保留的过程就叫作</span><span style="font-family: 'Times New Roman'">&#8220;</span>序列化&#8221;<span style="font-family: 宋体">。</span><br />可以把一个归档对象看作一种二进制流。象输入<span style="font-family: 'Times New Roman'">/</span><span style="font-family: 宋体">输出流一样，归档与文件有关并允许写缓冲区以及从硬盘读出或读入数据。输入</span><span style="font-family: 'Times New Roman'">/</span><span style="font-family: 宋体">输出流处理一系列</span><span style="font-family: 'Times New Roman'">ASCII</span><span style="font-family: 宋体">字符，但是归档文件以一种有效率、精练的格式处理二进制对象。</span></p>
<p class="p0"><strong>3<span style="font-family: 宋体">、</span><span style="font-family: 'Times New Roman'">CArchive</span><span style="font-family: 宋体">对象处理基础类型数据</span></strong></p>
<p class="p0"><br />必须在创建一个<span style="font-family: 'Times New Roman'">CArchive</span><span style="font-family: 宋体">对象之前，创建一个</span><span style="font-family: 'Times New Roman'">CFile</span><span style="font-family: 宋体">对象。另外，必须确信归档文件的装入</span><span style="font-family: 'Times New Roman'">/</span><span style="font-family: 宋体">存储与文件的打开模式是兼容的。每一个文件只限于一个活动归档文件。</span><br />当构造一个<span style="font-family: 'Times New Roman'">CArchive</span><span style="font-family: 宋体">对象时，要把它附加给表示一个打开文件的类</span><span style="font-family: 'Times New Roman'">CFile</span><span style="font-family: 宋体">（或派生类）的对象上。还要指定归档文件将用于装载还是存储。</span></p>
<p class="p0">示例：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">CFile&nbsp;file(</span><span style="color: #000000">"</span><span style="color: #000000">1.txt</span><span style="color: #000000">"</span><span style="color: #000000">,CFile::modeCreate&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&nbsp;CFile::modeWrite);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">定义一个文件流对象</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&nbsp;CArchive&nbsp;ar(</span><span style="color: #000000">&amp;</span><span style="color: #000000">file,CArchive::store);&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">定义一个序列化对象和文件流对象绑定并指定归档方式为储存，加载的方式为CArchive::load</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">4</span><span style="color: #000000">;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;ch</span><span style="color: #000000">=</span><span style="color: #000000">'</span><span style="color: #000000">a</span><span style="color: #000000">'</span><span style="color: #000000">;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;</span><span style="color: #0000ff">float</span><span style="color: #000000">&nbsp;f</span><span style="color: #000000">=</span><span style="color: #000000">1.3f</span><span style="color: #000000">;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;CString&nbsp;str(</span><span style="color: #000000">"</span><span style="color: #000000">aa</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" />&nbsp;ar</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">i</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">ch</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">f</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">str;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">储存到文件</span></div>
<p class="p0"></p><br />
<p class="p0"><strong>4<span style="font-family: 宋体">、</span>CArchive<span style="font-family: 宋体">对象</span>处理自定义对象类型数据</strong></p>
<p class="p0"><br />CArchive<span style="font-family: 宋体">对象不仅可以处理首要类型，而且还能处理为</span>序列化而设计的特殊的类的对象。可以序列化的类有以下特点：</p>
<p class="p0">1<span style="font-family: 宋体">、必须为</span>CObject<span style="font-family: 宋体">派生类。</span>直接或者间接的继承<span style="font-family: 'Times New Roman'">CObject</span><span style="font-family: 宋体">类。</span></p>
<p class="p0">2、必须重写CObject类的Serialize成员函数。</p>
<p class="p0">3<span style="font-family: 宋体">、</span>使用<span style="font-family: 'Times New Roman'">DECLARE_SERIAL</span><span style="font-family: 宋体">和</span><span style="font-family: 'Times New Roman'">IMPLEMENT_SERIAL</span><span style="font-family: 宋体">宏。</span></p>
<p class="p0">4<span style="font-family: 宋体">、必须有一个默认构造函数</span></p>
<p class="p0">在Serialize成员函数中完成保存和加载的功能。</p>
<p class="p0">DECLARE_SERIAL( class_name ) <span style="font-family: 宋体">参数为</span>当前类名。</p>
<p class="p0">IMPLEMENT_SERIAL( class_name, base_class_name, wSchema ) 第一个参数为当前类名，第二个参数为父类类名，第三个参数为该类的特定整型标识<span style="font-family: 'Times New Roman'">,</span><span style="font-family: 宋体">该标识将用来解序</span><span style="font-family: 'Times New Roman'">(</span><span style="font-family: 宋体">重新实例化</span><span style="font-family: 'Times New Roman'">)</span>，最小为<span style="font-family: 'Times New Roman'">0</span><span style="font-family: 宋体">。</span></p>
<p class="p0">示例：</p>
<p class="p0"></p>
<p class="p0"></p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #008000">//</span><span style="color: #008000">DrawBase.h</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;CDrawBase&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;CObject&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">继承自CObject</span><span style="color: #008000"><br /><img id="Codehighlighter1_59_518_Open_Image" onclick="this.style.display='none'; Codehighlighter1_59_518_Open_Text.style.display='none'; Codehighlighter1_59_518_Closed_Image.style.display='inline'; Codehighlighter1_59_518_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_59_518_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_59_518_Closed_Text.style.display='none'; Codehighlighter1_59_518_Open_Image.style.display='inline'; Codehighlighter1_59_518_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_59_518_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_59_518_Open_Text"><span style="color: #000000">{<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;DECLARE_SERIAL(CDrawBase)&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">第一个宏的位置，参数为当前类名</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CDrawBase();</span><span style="color: #008000">//</span><span style="color: #008000">必须有一个默认构造函数</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;onDraw(CDC</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pdc);<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">CDrawBase();<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;UINT&nbsp;m_PenStyle;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;m_PenWidth;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;m_BkMode;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;m_BrushStyle;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;m_issx;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;m_isyy;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;COLORREF&nbsp;m_PenColor;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;COLORREF&nbsp;m_BackgroundColor;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;COLORREF&nbsp;m_BrushColor;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;CPoint&nbsp;m_ptBegin;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;CPoint&nbsp;m_ptEnd;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Serialize(CArchive</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;ar);</span><span style="color: #008000">//</span><span style="color: #008000">重写了Serialize成员函数</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" /></span><span style="color: #000000">}</span></span><span style="color: #000000">;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">DrawBase.cpp</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">IMPLEMENT_SERIAL(CDrawBase,&nbsp;CObject,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">第二个宏的位置，第一个参数为当前类名，第二个参数为父类类名，第三个参数为该类的特定整型标识,该标识将用来解序(重新实例化)，最小为0</span><span style="color: #008000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;CDrawBase::Serialize(CArchive</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;ar)<br /><img id="Codehighlighter1_686_985_Open_Image" onclick="this.style.display='none'; Codehighlighter1_686_985_Open_Text.style.display='none'; Codehighlighter1_686_985_Closed_Image.style.display='inline'; Codehighlighter1_686_985_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_686_985_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_686_985_Closed_Text.style.display='none'; Codehighlighter1_686_985_Open_Image.style.display='inline'; Codehighlighter1_686_985_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_686_985_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_686_985_Open_Text"><span style="color: #000000">{<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;CObject::Serialize(ar);<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(ar.IsStoring())</span><span style="color: #008000">//</span><span style="color: #008000">保存，加载为ar.IsLoading()</span><span style="color: #008000"><br /><img id="Codehighlighter1_765_864_Open_Image" onclick="this.style.display='none'; Codehighlighter1_765_864_Open_Text.style.display='none'; Codehighlighter1_765_864_Closed_Image.style.display='inline'; Codehighlighter1_765_864_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_765_864_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_765_864_Closed_Text.style.display='none'; Codehighlighter1_765_864_Open_Image.style.display='inline'; Codehighlighter1_765_864_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_765_864_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_765_864_Open_Text"><span style="color: #000000">{<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ar&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_PenColor</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_PenStyle</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_PenWidth</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_BrushColor</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_BrushStyle</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_issx</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">m_isyy;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;Else&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">加载</span><span style="color: #008000"><br /><img id="Codehighlighter1_884_983_Open_Image" onclick="this.style.display='none'; Codehighlighter1_884_983_Open_Text.style.display='none'; Codehighlighter1_884_983_Closed_Image.style.display='inline'; Codehighlighter1_884_983_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_884_983_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_884_983_Closed_Text.style.display='none'; Codehighlighter1_884_983_Open_Image.style.display='inline'; Codehighlighter1_884_983_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_884_983_Closed_Text"><img src="http://www.cppblog.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_884_983_Open_Text"><span style="color: #000000">{<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ar&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_PenColor</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_PenStyle</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_PenWidth</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_BrushColor</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_BrushStyle</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_issx</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">m_isyy;<br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" />}</span></span></div>
<p class="p0"></p>
<p class="p0">重载提取（<span style="font-family: 'Times New Roman'">&gt;&gt;</span><span style="font-family: 宋体">）和插入（</span><span style="font-family: 'Times New Roman'">&lt;&lt;</span><span style="font-family: 宋体">）是方便的归档编程接口。它支持主要类型和</span><span style="font-family: 'Times New Roman'">CObject</span><span style="font-family: 宋体">派生类。</span><br />CArchive<span style="font-family: 宋体">还支持使用</span><span style="font-family: 'Times New Roman'">MFC Windows</span><span style="font-family: 宋体">套接字类</span><span style="font-family: 'Times New Roman'">CSocket</span><span style="font-family: 宋体">和</span><span style="font-family: 'Times New Roman'">CSocketFile</span><span style="font-family: 宋体">编程。</span><span style="font-family: 'Times New Roman'">IsBufferEmpty</span><span style="font-family: 宋体">成员函数也支持这种使用。</span></p>
<p class="p0">一些集合类也支持序列化，<span style="font-family: 'Times New Roman'">CObArray,Vector,CPtrArray</span><span style="font-family: 宋体">。</span></p>
<p class="p0"></p>
<p class="p0">在<span style="font-family: 'Times New Roman'">MFC</span><span style="font-family: 宋体">文档</span><span style="font-family: 'Times New Roman'">-</span><span style="font-family: 宋体">视图结构中，</span><span style="font-family: 'Times New Roman'">Doc</span><span style="font-family: 宋体">类是被系统设定好支持序列化的类，在</span><span style="font-family: 'Times New Roman'">Doc</span><span style="font-family: 宋体">类中重写</span>Serialize<span style="font-family: 宋体">成员函数</span>。在函数中对你要保存的对象序列化。</p>
<p class="p0">完成之后，点击菜单栏上的保存和打开就可以实现序列化了。</p>
<p class="p0">&nbsp;</p><br /><br /><br /><img src ="http://www.cppblog.com/cxiaojia/aggbug/198177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2013-03-02 18:04 <a href="http://www.cppblog.com/cxiaojia/archive/2013/03/02/198177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NoSql数据库学习汇总</title><link>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195875.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 01 Dec 2012 15:13:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195875.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/195875.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195875.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/195875.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/195875.html</trackback:ping><description><![CDATA[<span style="background-color: yellow;">MongoDB</span><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_7" href="http://www.cnblogs.com/huangxincheng/archive/2012/02/18/2356595.html"><br />8天学通MongoDB&#8212;&#8212;第一天 基础入门<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_6" href="http://www.cnblogs.com/huangxincheng/archive/2012/02/19/2357846.html">8天学通MongoDB&#8212;&#8212;第二天 细说增删查改<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_5" href="http://www.cnblogs.com/huangxincheng/archive/2012/02/21/2361205.html">8天学通MongoDB&#8212;&#8212;第三天 细说高级操作<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_4" href="http://www.cnblogs.com/huangxincheng/archive/2012/02/29/2372699.html">8天学通MongoDB&#8212;&#8212;第四天 索引操作<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_3" href="http://www.cnblogs.com/huangxincheng/archive/2012/03/04/2379755.html">8天学通MongoDB&#8212;&#8212;第五天 主从复制<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_2" href="http://www.cnblogs.com/huangxincheng/archive/2012/03/07/2383284.html">8天学通MongoDB&#8212;&#8212;第六天 分片技术</a><br /><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_1" href="http://www.cnblogs.com/huangxincheng/archive/2012/03/08/2384571.html">8天学通MongoDB&#8212;&#8212;第七天 运维技术<br /></a><a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_0" href="http://www.cnblogs.com/huangxincheng/archive/2012/03/09/2386054.html">8天学通MongoDB&#8212;&#8212;第八天 驱动实践</a><img src ="http://www.cppblog.com/cxiaojia/aggbug/195875.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-12-01 23:13 <a href="http://www.cppblog.com/cxiaojia/archive/2012/12/01/195875.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>8种Nosql数据库系统对比（转）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195865.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 01 Dec 2012 09:12:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195865.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/195865.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/195865.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/195865.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 导读：Krist&#243;f Kov&#225;cs 是一位软件架构师和咨询顾问，他最近发布了一片对比各种类型nosql数据库的文章。文章由敏捷翻译 &#8211;&nbsp;唐尤华编译。如需转载，请参见文后声明。虽然SQL数据库是非常有用的工具，但经历了15年的一支独秀之后垄断即将被打破。这只是时间问题：被迫使用关系数据库，但最终发现不能适应需求的情况不胜枚举。但是NoSQL数据库之间的不同，...&nbsp;&nbsp;<a href='http://www.cppblog.com/cxiaojia/archive/2012/12/01/195865.html'>阅读全文</a><img src ="http://www.cppblog.com/cxiaojia/aggbug/195865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-12-01 17:12 <a href="http://www.cppblog.com/cxiaojia/archive/2012/12/01/195865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Nosql入门知识（转）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195864.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 01 Dec 2012 08:57:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195864.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/195864.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/12/01/195864.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/195864.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/195864.html</trackback:ping><description><![CDATA[<div><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">1. NoSQL其实是关系型数据库相对应的，是no relational 即非关系型数据库；web2.0特别是一些用户访问量比较大的网站如：www.taobao.com weibo.com baidu.com&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">每秒的访问量可能是上万次(10K);传统的关系型数据库 mysql oracle 每秒进行10K次数据查询还可以勉强应付，但是如果是每秒10K次读写数据库，因为数据库的数据都是卸载磁盘中，所以磁盘IO也是支撑不住每秒10K的读写。</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">在web的架构中，数据库是最难进行横向扩展的(通过简单的添加机器和硬件，也就是添加一些服务节点来提高负载均衡能力)；对于7*24小时在线的网站来说，对关系型数据库进行升级和扩展(分布式扩展--分库分表)是非常痛苦的事情，往往要进行停机维护；但这种对www.taobao.com 来说是非常丑陋的事情。[--可不可以添加几台服务器然后把复制，然后进行负载均衡--]。</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">NoSQL 是采用key/value的结构来存储数据，而且大多数的NoSQL采用内存来存储数据，一段时间后把数据同步到磁盘中；由于使用<strong>内存保存</strong>数据很好地解决了<strong>高并发读写</strong>的问题；其次NoSQL提供了根据key值进行横向分表(比如：用户id，每2000w数据放到一台数据库服务器中的一张用户表中)；同时实现了主从数据库互备，这样可以让数据库的动态迁移变得简单，让数据库服务器的横向扩展变得容易了。</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">2. 分布式数据库的CAP理论</p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;CAP理论<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">是说</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">Consistency</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">（一致性），</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">&nbsp;Availability</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">（可用性），</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">&nbsp;partition tolerance</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">（分布）三部分系统；而且任何系统只会满足两个，不会有任何的系统会同时满足这三个条件；在传统的关系型数据库中是强调C 一致性，但是在满足高可用性(高并发时效率不高)，高扩展性(分布式数据库进行横向扩展)存在一定的缺陷。但是NoSQL在进行设计的时候就是针对并发海量数据存储的情况下进行设计的，在这种高并发海量数据下数据一致性并不像银行那样保持数据的强一致性，所以NoSQL&#183;放弃强一致性的追求，从而达到更高的可用性和扩展性，通过&#8220;<strong>鸽巢原理</strong>&#8221;达到最终的一致性。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; text-indent: 32px; ">现在的数据库系统肯定是同一个时刻有多个进程对数据库进行读写操作，假设现在有3个进程(A、B、C)对数据库的某表进行操作，</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "></p><ul style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">强一致性：A写入的数据x，B、C可以读到数据x</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">弱一致性：A写入的数据x，B、C一段时间内读不到，最后会读到</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">最终一致性：是一种特殊的一致性，保证在一段时间内没有数据的更新，但所有的返回都是把最新的数据返回；---缓存的概念，一段时间后把数据更新到数据库，达到最终一致性。</span></li></ul><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">3. 哈希算法</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">(1). 哈希算法的基本原理：</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">&nbsp; &nbsp; &nbsp;哈希算法的提出和应用背景，对于一个庞大的字符串数组array，给你一个字符串让你判断它是否在这个字符串数组中并找到它，最好的办法就是把这个庞大的字符串数组构建成一个哈希表，然后在进行查询是否有这个字符串。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">&nbsp;(2).构建hash table的过程：一般是采用一个32的整数来代表一个字符串，首先这个array的字符串已经存在内存或者磁盘中，我们要做的只是按照一定的算法把每个字符串映射到一个32位的整数，每个int占4个字节，在字符串中每个字符都占一个字节；这样就建立了字符串与32位整数的映射，然后根据程序大小设定一个hash table的Size(<strong>这个Size确保所有的int % Size的值是唯一的--取最大值即可</strong>)，这个把刚才得到的所有字符串对应的32位整数对这个Size进行取模，这个模值就是此整数在hash table的位置；这个位置与每一个字符串又建立了一个映射关系；这样让你查询这个str是否在array中？</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><ul><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">首先，是把这个str，用相同的哈希算法进行编码----&gt;映射到一个32位的int型数据 num</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">然后，把这个num % Size 获取此字符串在hash table里面的位置；</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">然后，判断hash table 此位置是否已经有数据占用，如果已经占用说明在array里面有一个字符串对应的32位整数与str的32位整数相同，在一个字符串对应唯一一个32位整数的前提条件下，就说明array里面存在字符串str。</span></li></ul><div><div bg_html"="" style="width: 687px; "><div><div><strong>[html]</strong>&nbsp;<a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="view plain" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">view plain</a><a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="copy" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">copy</a><div style="position: absolute; left: 520px; top: 1624px; width: 18px; height: 18px; z-index: 99; border-image: initial; "><embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_1" align="center" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&amp;width=18&amp;height=18" wmode="transparent"></div></div></div><ol start="1" style="border-width: initial; border-color: initial; "><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span style="border-width: initial; border-color: initial; ">int&nbsp;GetHashTablePos(char&nbsp;*lpszString,&nbsp;SOMESTRUCTURE&nbsp;*lpTable,&nbsp;int&nbsp;nTableSize)&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">{&nbsp;//lpszSring--要查询的字符串；lpTable&nbsp;哈希表；nTableSize是哈希表的Size&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHash</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">HashString</span><span style="border-width: initial; border-color: initial; ">(lpszString),&nbsp;</span><span style="border-width: initial; border-color: initial; color: red; ">nHashPos</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">nHash</span><span style="border-width: initial; border-color: initial; ">&nbsp;%&nbsp;nTableSize;&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">if&nbsp;(lpTable[nHashPos].bExists&nbsp;&amp;&amp;&nbsp;!strcmp(lpTable[nHashPos].pString,&nbsp;lpszString))&nbsp;&nbsp;//时间复杂度是O(1)&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;return&nbsp;nHashPos;&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">else&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;return&nbsp;-1;&nbsp;//Error&nbsp;value&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">}&nbsp;&nbsp;</span></li></ol></div>(3). &nbsp;上面的处理方法是假设一个字符串通过一个哈希算法只得到唯一一个hashcode(32为int整数)；但是如果存在两个整数在同一个哈希算法得到同一个hashcode，那这个查询就不正确的，虽然这个可能性比较小，但确实存在这个风险。</div><div><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">采用的解决办法是用多个不同的哈希算法来校验，两个str 在三个不同的哈希算法得到的hashcode都相同的概率是：<span style="font-family: song, Verdana; line-height: 22px; ">1/18889465931478580854784；可以认为是OK的。</span></span></div><div><span style="font-family: song, Verdana; "></span><div bg_html"="" style="width: 687px; "><div><div><strong>[html]</strong>&nbsp;<a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="view plain" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">view plain</a><a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="copy" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">copy</a><div style="position: absolute; left: 520px; top: 2001px; width: 18px; height: 18px; z-index: 99; border-image: initial; "><embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_2" align="center" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&amp;width=18&amp;height=18" wmode="transparent"></div></div></div><ol start="1" style="border-width: initial; border-color: initial; "><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span style="border-width: initial; border-color: initial; ">int&nbsp;GetHashTablePos(char&nbsp;*lpszString,&nbsp;MPQHASHTABLE&nbsp;*lpTable,&nbsp;int&nbsp;nTableSize)&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">{&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">const&nbsp;int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">HASH_OFFSET</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">0</span><span style="border-width: initial; border-color: initial; ">,&nbsp;</span><span style="border-width: initial; border-color: initial; color: red; ">HASH_A</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">1</span><span style="border-width: initial; border-color: initial; ">,&nbsp;</span><span style="border-width: initial; border-color: initial; color: red; ">HASH_B</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">2</span><span style="border-width: initial; border-color: initial; ">;&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHash</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">HashString</span><span style="border-width: initial; border-color: initial; ">(lpszString,&nbsp;HASH_OFFSET);&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHashA</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">HashString</span><span style="border-width: initial; border-color: initial; ">(lpszString,&nbsp;HASH_A);&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHashB</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">HashString</span><span style="border-width: initial; border-color: initial; ">(lpszString,&nbsp;HASH_B);&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">int&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHashStart</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">nHash</span><span style="border-width: initial; border-color: initial; ">&nbsp;%&nbsp;nTableSize,&nbsp;</span><span style="border-width: initial; border-color: initial; color: red; ">nHashPos</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;</span><span style="border-width: initial; border-color: initial; color: blue; ">nHashStart</span><span style="border-width: initial; border-color: initial; ">;&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">while&nbsp;(lpTable[nHashPos].bExists)&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">{&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;if&nbsp;(lpTable[nHashPos]<span style="border-width: initial; border-color: initial; color: red; ">.nHashA</span><span style="border-width: initial; border-color: initial; ">&nbsp;==&nbsp;nHashA&nbsp;&amp;&amp;&nbsp;lpTable[nHashPos]</span><span style="border-width: initial; border-color: initial; color: red; ">.nHashB</span><span style="border-width: initial; border-color: initial; ">&nbsp;==&nbsp;nHashB)&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;return&nbsp;nHashPos;&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;else&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;<span style="border-width: initial; border-color: initial; color: red; ">nHashPos</span><span style="border-width: initial; border-color: initial; ">&nbsp;=&nbsp;(nHashPos&nbsp;+&nbsp;1)&nbsp;%&nbsp;nTableSize;&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;if&nbsp;(<span style="border-width: initial; border-color: initial; color: red; ">nHashPos</span><span style="border-width: initial; border-color: initial; ">&nbsp;==&nbsp;nHashStart)&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">}&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">return&nbsp;-1;&nbsp;//Error&nbsp;value&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">}&nbsp;&nbsp;</span></li></ol></div><br />这样就可以保证万无一失了！</div><div></div><div>(4). 常见的哈希算法：MD5 SHA &nbsp;SHA-1等都是常用的哈希算法，而且他们都属于混合哈希算法，除了混合哈希算法还有加法、乘法、除法的哈希算法；</div><div>所以，在比较一个文件是否发生变化的方法出了可以用最后修改时间来判断，也可以用其哈希code来比较，比如用MD5来比较，如果其MD5都变化了则文件一定被修改了。<br /></div></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; "><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">4. Tair 缓存也是一种 基于key/value的NoSQL结构开发的一种缓存机制，其实质也是NoSQL数据库，不过是key/value结构而且是用内存来存储数据，所以用把Tair叫做缓存。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">&nbsp;<a href="http://www.open-open.com/lib/view/open1324345273311.html" style="color: #336699; text-decoration: none; ">http://www.open-open.com/lib/view/open1324345273311.html</a>&nbsp;&nbsp;<a href="http://www.open-open.com/lib/view/open1324345273311.html" style="color: #336699; text-decoration: none; ">点击打开链接</a><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; "><br /></span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">5. 关系型数据库的事务(ACID)</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">(1). 事务(Transaction)：Transaction是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)，事务一般由高级数据语言(C++ Java SQL)等写的用户程序引起的，并用begin transaction----end transaction 来界定一个完整的事务</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><div bg_html"="" style="width: 687px; "><div><div><strong>[html]</strong>&nbsp;<a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="view plain" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">view plain</a><a href="http://blog.csdn.net/caoshuming_500/article/details/7524294#" title="copy" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">copy</a><div style="position: absolute; left: 520px; top: 2832px; width: 18px; height: 18px; z-index: 99; border-image: initial; "><embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_3" align="center" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&amp;width=18&amp;height=18" wmode="transparent"></div></div></div><ol start="1" style="border-width: initial; border-color: initial; "><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">&lt;</span><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">begin</span><span style="border-width: initial; border-color: initial; ">&nbsp;transaction</span><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">&gt;</span><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;</span></span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">****&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">****&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">****&nbsp;&nbsp;</span></li><li style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">&lt;/</span><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">end</span><span style="border-width: initial; border-color: initial; ">&nbsp;transaction</span><span style="border-width: initial; border-color: initial; color: #993300; font-weight: bold; ">&gt;</span><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;</span></span></li></ol></div>一个完整的事务由<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">begin transaction----end transaction &nbsp;里面的所有操作组成；在关系型数据库中一个事务可以是一条SQL语句或一组SQL语句或者是一个程序；事务是并发和回滚的基本单位。</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">(2). 事务的ACID属性：</span></div><div style="color: #333333; font-family: Arial; line-height: 26px; text-align: left; background-color: #ffffff; "><ul><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">Atomicity(原子性)：一个事务是一个不可分割的完整单元，一个transaction里面的所有操作要么都做完，要么都不做；当中间一个操作失败把所有已经做的操作都回滚！</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">Consistency(一致性)：数据库在一个事务开始前是一致性的，在这个事务执行完毕后仍然是一致性的；只是从一个一致性状态到另一个一致性状态；但都是一致性的</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">Isolation(隔离性)：一个事务的执行不能被其他事务所打扰，即一个事务内部操作及使用的数据对并发的事务是隔离的，<strong>并发执行的事务之间互相不干扰</strong>(<strong>不理解)</strong>!!</span></li><li><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">Durablity(持久性)：也就永久性(Permanence)，即一个事务一旦执行完毕，则它对数据库的更新是持久性的，即不受其他操作的影响；也就是事务修改了数据库了</span></li></ul><div><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; ">这个ACID的属性是关系型数据库(DBMS)非常重要的属性，在执行数据库操作时必须满足ACID属性，其中AI是我们编程中要注意的地方。</span></div></div></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/195864.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-12-01 16:57 <a href="http://www.cppblog.com/cxiaojia/archive/2012/12/01/195864.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs2005,vs2008解决添加变量添加函数添加类时脚本错误问题</title><link>http://www.cppblog.com/cxiaojia/archive/2012/11/12/195070.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 12 Nov 2012 04:35:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/11/12/195070.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/195070.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/11/12/195070.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/195070.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/195070.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">给一个控件添加变量的时候出现的脚本错误问题</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">解决方案：</span></p>
<p style="text-indent: -18pt; margin: 0cm 0cm 0pt 18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin" lang="EN-US"><span style="mso-list: Ignore"><font face="Calibri">1．</font><span style="font: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">打开开始菜单，点击运行按钮，输入</span><span lang="EN-US"><font face="Calibri">regedit</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，进入注册表界面</span></p>
<p style="text-indent: -18pt; margin: 0cm 0cm 0pt 18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin" lang="EN-US"><span style="mso-list: Ignore"><font face="Calibri">2．</font><span style="font: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">找到目录</span><font face="Calibri"> <span lang="EN-US">HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones</span></font></p>
<p style="text-indent: -18pt; margin: 0cm 0cm 0pt 18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin" lang="EN-US"><span style="mso-list: Ignore"><font face="Calibri">3．</font><span style="font: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">查看此目录下是否存在</span><span lang="EN-US"><font face="Calibri">1000</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">目录，如果不存在则建立此目录</span></p>
<p style="text-indent: -18pt; margin: 0cm 0cm 0pt 18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin" lang="EN-US"><span style="mso-list: Ignore"><font face="Calibri">4．</font><span style="font: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">在</span><span lang="EN-US"><font face="Calibri">1000</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">目录下创建</span><span lang="EN-US"><font face="Calibri">DWORD</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">值，名字为</span><span lang="EN-US"><font face="Calibri">1207</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，值为</span><span lang="EN-US"><font face="Calibri">0</font></span></p>
<p style="text-indent: -18pt; margin: 0cm 0cm 0pt 18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin" lang="EN-US"><span style="mso-list: Ignore"><font face="Calibri">5．</font><span style="font: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">重启</span><span lang="EN-US"><font face="Calibri">vs2005/2008</font></span></p> <img src ="http://www.cppblog.com/cxiaojia/aggbug/195070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-11-12 12:35 <a href="http://www.cppblog.com/cxiaojia/archive/2012/11/12/195070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>优先队列（二叉堆）模板</title><link>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 15 Sep 2012 06:40:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/190272.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/190272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/190272.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">=</span><span style="color: #000000; ">100003</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;BinaryHeap<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;Size;<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;Tarr;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;BinaryHeap();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;insert(T&nbsp;x);<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;deleteMin();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">BinaryHeap();<br />};<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::BinaryHeap()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;T[MAX</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Tarr</span><span style="color: #000000; ">==</span><span style="color: #000000; ">NULL)&nbsp;{cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">创建数组失败</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;;}<br />&nbsp;&nbsp;&nbsp;&nbsp;Size</span><span style="color: #000000; ">=</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}<br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::insert(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">Size;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Size</span><span style="color: #000000; ">==</span><span style="color: #000000; ">MAX)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Size;Tarr[i</span><span style="color: #000000; ">/</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">x;i</span><span style="color: #000000; ">/=</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[i</span><span style="color: #000000; ">/</span><span style="color: #000000; ">2</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">x;<br />}<br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />T&nbsp;BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::deleteMin()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Size</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;minem</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;lastem</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[Size</span><span style="color: #000000; ">--</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i,child;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;i</span><span style="color: #000000; ">*</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">Size;i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">child)&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;child</span><span style="color: #000000; ">=</span><span style="color: #000000; ">i</span><span style="color: #000000; ">*</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(child</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">Size</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">Tarr[child</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Tarr[child])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">child;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(lastem</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">Tarr[child])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[child];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">lastem;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;minem;<br />}<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::</span><span style="color: #000000; ">~</span><span style="color: #000000; ">BinaryHeap()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;delete[]&nbsp;Tarr;<br /><br />}<br /><br /></span></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/190272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-09-15 14:40 <a href="http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>哈希模板</title><link>http://www.cppblog.com/cxiaojia/archive/2012/09/12/190436.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Wed, 12 Sep 2012 12:06:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/09/12/190436.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/190436.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/09/12/190436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/190436.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/190436.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;&nbsp;MAX=1000003;<br />template&nbsp;&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;hash<br />{<br /><span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;next[MAX];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;head[MAX];<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;key[MAX];<br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;hash();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;search(T&nbsp;x);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;push(T&nbsp;x);<br /><br /><br />};<br />template&nbsp;&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />hash&lt;T&gt;::hash()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;pos=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(next,-1,<span style="color: #0000FF; ">sizeof</span>(next));<br />&nbsp;&nbsp;&nbsp;&nbsp;memset(head,-1,<span style="color: #0000FF; ">sizeof</span>(head));<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">memset(key,-1,sizeof(key));</span><span style="color: #008000; "><br /></span>}<br />template&nbsp;&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />inline&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;hash&lt;T&gt;::search(<span style="color: #0000FF; ">const</span>&nbsp;T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;temp=x%MAX;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;t=head[temp];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(t!=-1)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(key[t]==x)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t=next[t];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br />}<br />template&nbsp;&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />inline&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;hash&lt;T&gt;::push(<span style="color: #0000FF; ">const</span>&nbsp;T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;temp=x%MAX;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(head[temp]!=-1)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next[pos]=head[temp];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;head[temp]=pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;key[pos]=x;<br />&nbsp;&nbsp;&nbsp;&nbsp;pos++;<br />}</div><img src ="http://www.cppblog.com/cxiaojia/aggbug/190436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-09-12 20:06 <a href="http://www.cppblog.com/cxiaojia/archive/2012/09/12/190436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一天一个shell实例（3）定时备份文件</title><link>http://www.cppblog.com/cxiaojia/archive/2012/09/07/189789.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Fri, 07 Sep 2012 03:00:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/09/07/189789.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/189789.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/09/07/189789.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/189789.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/189789.html</trackback:ping><description><![CDATA[<div>   	 	 	 	  <p style="margin-bottom: 0cm">写一个备份文件的脚本，利用crontab定时执行。</p> <p style="margin-bottom: 0cm"><br /> </p> <p style="margin-bottom: 0cm">步骤如下：</p> <p style="margin-bottom: 0cm">1，设置备份目的目录</p> <p style="margin-bottom: 0cm">2，进入目的目录</p> <p style="margin-bottom: 0cm">3，获取时间，设置备份文件名</p> <p style="margin-bottom: 0cm">4，备份文件</p> </div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#</span><span style="color: #000000; ">!/</span><span style="color: #000000; ">bin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bash<br /><br />DIRNAME</span><span style="color: #000000; ">=</span><span style="color: #000000; ">`ls&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">root&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;grep&nbsp;bak`&nbsp; #</span><span style="color: #000000; ">1</span><span style="color: #000000; "><br /><br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;[&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">z&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">$DIRNAME</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;]&nbsp; #</span><span style="color: #000000; ">2</span><span style="color: #000000; "><br />then<br />mkdir&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">root</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bak&nbsp; #</span><span style="color: #000000; ">3</span><span style="color: #000000; "><br />fi<br /><br />cd&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">root</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bak&nbsp; #</span><span style="color: #000000; ">4</span><span style="color: #000000; "><br /><br />YY</span><span style="color: #000000; ">=</span><span style="color: #000000; ">`date&nbsp;</span><span style="color: #000000; ">+%</span><span style="color: #000000; ">y`&nbsp;&nbsp; #</span><span style="color: #000000; ">5</span><span style="color: #000000; "><br />MM</span><span style="color: #000000; ">=</span><span style="color: #000000; ">`date&nbsp;</span><span style="color: #000000; ">+%</span><span style="color: #000000; ">m`<br />DD</span><span style="color: #000000; ">=</span><span style="color: #000000; ">`date&nbsp;</span><span style="color: #000000; ">+%</span><span style="color: #000000; ">d`<br />etc</span><span style="color: #000000; ">=</span><span style="color: #000000; ">_etc<br /><br />BACKETC</span><span style="color: #000000; ">=</span><span style="color: #000000; ">$YY$MM$DD$etc.tar.gz&nbsp; #</span><span style="color: #000000; ">6</span><span style="color: #000000; "><br />tar&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">zcvf&nbsp;$BACKETC&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc&nbsp; #</span><span style="color: #000000; ">7</span><span style="color: #000000; "><br />echo&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">fileback&nbsp;finished!</span><span style="color: #000000; ">"</span><span style="color: #000000; "><br /></span></div><div>   	 	 	 	  <p style="margin-bottom: 0cm">#1：获取root/bak字符串</p> <p style="margin-bottom: 0cm">#2：-z选项判断是否为空</p> <p style="margin-bottom: 0cm">#3：如果为空就创建目录</p> <p style="margin-bottom: 0cm">#4：进入该目录</p> <p style="margin-bottom: 0cm">#5：获取当前时间</p> <p style="margin-bottom: 0cm">#6：设置备份文件名</p> <p style="margin-bottom: 0cm">#7：将/etc目录下所有文件打包备份</p> <p style="margin-bottom: 0cm">         &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; -z 用gizp压缩和解压缩文件，若加上此选项创建的压缩包，解压的时候也许要加上此选项</p> <p style="margin-bottom: 0cm">         &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; -c 创建新的包</p> <p style="margin-bottom: 0cm">         &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; -v 详细报告tar处理文件的信息</p> <p style="margin-bottom: 0cm">         &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; -f 使用压缩文件或设备，该选项通常事必选的</p> </div><br /><br /><div>   	 	 	 	  <p style="margin-bottom: 0cm">定时执行脚本需要修改etc中的 crontab文件</p> </div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">root@Notebook</span><span style="color: #000000; ">-</span><span style="color: #000000; ">PC:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc#&nbsp;vi&nbsp;crontab<br /><br />#&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">crontab:&nbsp;system</span><span style="color: #000000; ">-</span><span style="color: #000000; ">wide&nbsp;crontab<br /><br />#&nbsp;Unlike&nbsp;any&nbsp;other&nbsp;crontab&nbsp;you&nbsp;don</span><span style="color: #000000; ">'</span><span style="color: #000000; ">t&nbsp;have&nbsp;to&nbsp;run&nbsp;the&nbsp;`crontab</span><span style="color: #000000; ">'</span><span style="color: #000000; "><br /><br />#&nbsp;command&nbsp;to&nbsp;install&nbsp;the&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;version&nbsp;when&nbsp;you&nbsp;edit&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&nbsp;file<br /><br />#&nbsp;and&nbsp;files&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cron.d.&nbsp;These&nbsp;files&nbsp;also&nbsp;have&nbsp;username&nbsp;fields,<br /><br />#&nbsp;that&nbsp;none&nbsp;of&nbsp;the&nbsp;other&nbsp;crontabs&nbsp;</span><span style="color: #0000FF; ">do</span><span style="color: #000000; ">.<br /><br />SHELL</span><span style="color: #000000; ">=/</span><span style="color: #000000; ">bin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sh<br /><br />PATH</span><span style="color: #000000; ">=/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">local</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">local</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bin:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bin:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin:</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">bin<br /><br />#&nbsp;m&nbsp;h&nbsp;dom&nbsp;mon&nbsp;dow&nbsp;user&nbsp;&nbsp;command<br /><br /></span><span style="color: #000000; ">17</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;root&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;run</span><span style="color: #000000; ">-</span><span style="color: #000000; ">parts&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">report&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cron.hourly<br /><br /></span><span style="color: #000000; ">25</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;root&nbsp;&nbsp;&nbsp;&nbsp;test&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">x&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">anacron&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;(&nbsp;cd&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;run</span><span style="color: #000000; ">-</span><span style="color: #000000; ">parts&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">report&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cron.daily&nbsp;)<br /><br /></span><span style="color: #000000; ">47</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">7</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;root&nbsp;&nbsp;&nbsp;&nbsp;test&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">x&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">anacron&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;(&nbsp;cd&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;run</span><span style="color: #000000; ">-</span><span style="color: #000000; ">parts&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">report&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cron.weekly&nbsp;)<br /><br /></span><span style="color: #000000; ">52</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">6</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;root&nbsp;&nbsp;&nbsp;&nbsp;test&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">x&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">sbin</span><span style="color: #000000; ">/</span><span style="color: #000000; ">anacron&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;(&nbsp;cd&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;run</span><span style="color: #000000; ">-</span><span style="color: #000000; ">parts&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">report&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">etc</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cron.monthly&nbsp;)<br /><br /></span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;root&nbsp;&nbsp;&nbsp;&nbsp;test4.sh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #加上此行，表示每天1时执行脚本&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />#<br /></span></div><br /><div>   	 	 	 	  <p style="margin-bottom: 0cm">* * * * *           #表示每分钟</p> <p style="margin-bottom: 0cm">1 * * * *           #表示每小时的第一分钟</p> <p style="margin-bottom: 0cm">2 12 * * *         #表示每天的12：02</p> <p style="margin-bottom: 0cm">0-59/2 * * * *  #每两分钟执行一次任务</p> </div><br /><br /><br /><br /><img src ="http://www.cppblog.com/cxiaojia/aggbug/189789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-09-07 11:00 <a href="http://www.cppblog.com/cxiaojia/archive/2012/09/07/189789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>