﻿<?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++博客-点点滴滴-随笔分类-10 服务器</title><link>http://www.cppblog.com/ming81/category/15288.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 06 Jun 2017 07:13:43 GMT</lastBuildDate><pubDate>Tue, 06 Jun 2017 07:13:43 GMT</pubDate><ttl>60</ttl><item><title>(搬运工)LOL匹配规则 </title><link>http://www.cppblog.com/ming81/archive/2012/11/14/195185.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 14 Nov 2012 03:07:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/11/14/195185.html</guid><description><![CDATA[<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">很多人抱怨看不懂，我来个精简比喻版的：</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">有个篮球联盟，有无数个球员和大概20个等级的联赛。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">所有球员都是10级联赛的成员，他们自由组合互相比赛，赢的人，升级到11级联赛，输的人降到9级联赛。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">然后每个等级联赛再次开赛，又有的人升级有的人降级，最终这20级的联赛都有球员参加。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">我们的大量的数据证明，一个球员的水平，会让其稳定在大约3个联赛之间，也就是科比是参加20级联赛的，且当他和4个17级联赛的人组队，基本不会输给17级联赛的人。且，把科比降到10级联赛，他会轻松的在20局之内回到20级。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">理想情况下，球员都是在跟自己同样经历的球员玩，一个中等水平玩家完全不会匹配到科比，科比也不会匹配到刚玩游戏的玩家。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">事实上匹配系统的分级会比这个更复杂更智能，采用的是国际象棋所采用的elo系统。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">再增加个FAQ：</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">Q：系统为了保持胜率50%，是否会在我连胜后故意塞给我一些菜队友让我输？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">A：系统的目的不是为了保持你的胜率，而是让水平差不多的玩家一起玩。当你和水平差不多的玩家一起玩时胜率会趋近50%，所以，系统是不会故意坑你的。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">Q：我才100胜，为什么系统老匹配600胜的玩家给我？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">A：胜场并不能反应一个人的水平。如果把匹配系统比作跑步，练习了3年才能跑进11秒的和第一次就跑进11秒的人我们是同等看待的。匹配系统基于水平而不是基于经验。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">Q：我胜率60%，为什么匹配40%胜率的队友、60%胜率的对手给我？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">A：胜率也不能反映水平。匹配系统不但要看你是否赢了，也要看你赢了谁。就像war3的sky在职业圈胜率其实并不高，但是虐一般的玩家胜率是100%。同样水平的玩家，会因为随机匹配到对手的关系，胜率会40%~60%不等。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">Q：你说水平差不多，为什么我觉得他们这么菜？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">A：<strong style="word-wrap: break-word">匹配系统提供的是公平的机会，而未必是你理想的结果。</strong><strong style="word-wrap: break-word">我们能追求系统公正，但是无法预测玩家单局内的表现。</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">系统100%匹配曼联对阵皇马，但是不能保证某一次曼联不会4：0碾压皇马，且在这局中，C罗表现yts，完全就在拖后腿。或者曼联也可能连胜皇马3次之类的。但是，系统只会把曼联去匹配皇马而不会出现曼联对阵中超深圳队。具体到某一局是皇马赢还是曼联赢取决于那一场的排兵布阵，临场发挥，以及战术意图。<br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">如果这个坑爹玩家真的不在你的水平等级，他就会一直坑队友，一直输，等级一直降低，这样会让他离开你的匹配范围，让他不再可以和你匹配到。根据我们的数据，玩家的elo基本是稳定在较小范围内的。这也就是深圳队和皇马的差距，也是中国国家队能赢法国队，确永远打不进世界杯的理由。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">系统没办法给你完美队友，玩家会因为很多原因发挥不好：使用不会的英雄、打了不想打的位置、玩法风格和队友不够搭配，前期不利想挂机等等。但是你和对方玩家遇到这种情况的概率是相同的，系统并不会偏袒任何一方。所以想要完美队友，请和朋友组队，不过那样你也会碰见更厉害的对手。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">如果大家在如何鉴定玩家水平上有好的想法欢迎提，但是如果想要通过抱怨玩家游戏内表现来证明匹配系统不公平，就是在和风车决斗了。每个人的看法都不一样的，系统判断他和你在遇到同样的队友和对手时候，胜率差不多，这也是我们目前能做到最好的了。</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">以下是文章的正文。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><br style="word-wrap: break-word" /></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">概述：</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">匹配系统的目的如下，优先级从高到低：</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">1、 保护新手不被有经验的玩家虐；让高手局中没有新手。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">2、 创造竞技和公平的游戏对局，使玩家的游戏乐趣最大化。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">3、 无需等待太久就能找到对手进入游戏。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">匹配系统尽其所能的匹配水平接近的玩家，玩家的水平是来自他们在此之前赢了谁以及他们对手的水平。当你战胜对手，系统会认为你更强，当你输给对手，系统会认为你更弱。虽然这对于某一局游戏并不是那么的公平，但是长期来看，对于多局游戏是相当的公平：因为好的玩家总会对游戏结果造成正面的、积极的影响。我们使用了这样一个方法测试：给水平高的玩家一个新帐号，然后看他们游戏数局后的结果。我们通过大量的测试来证明了我们的想法。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">并且，匹配系统知道预先组队的玩家有一些优势，如果你是预先组队，会给你一些更强的玩家。我们用一些非常巧妙的数学方法来解决预先组队的玩家VS solo玩家的匹配公平问题。我甚至让两个数学博士来验证，他们都说给力！</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">匹配是怎么完成的？</strong></p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">首先，系统将你放进适当的匹配池里&#8212;&#8212;根据游戏模式（匹配模式、排位solo/双人、排位5人、其他模式等等）</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">然后，系统会尝试将匹配池里的人分到更细的匹配池里&#8212;&#8212;5人组队 VS 5人组队，低等级新手 vs 其他一些低等级新手，如此这般。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">当你在匹配池中，系统会开始尝试找到合适的配对，目标是撮合一个双方获胜机会都为50%的游戏。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">第1步：确定你的实力：</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*如果你是solo，就直接使用你的个人匹配分（也就是elo值，匹配模式和排位赛有不同的匹配分）</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*如果你是预先组队的，你的匹配分是你队伍的平均分，并且会根据你组队的规模稍微提高一些，这样才能保证你匹配到更强的对手来抵消你组队的优势。我和一个计算机生物学的博士（Computational Biology Ph.D）通过研究成百上千的游戏结果，计算出了预先组队到底有多大的优势。我们还在幕后做了一些其他调整，比如新手和高玩组队，比如某地图上蓝队和紫队的玩家哪个更有优势，诸如此类。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">第2步：确定你合适的对手：</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*首先，系统会基于你的elo值，给你匹配跟你非常相近的玩家。最终，系统会放宽匹配的条件，给你一些不是那么完美的匹配，因为你肯定也不想永远匹配不到人。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*新手会得到一些特殊的保护，通常新手只会匹配到其他新手（在成熟的服务器里，这个比例达到了99%+。除非这个新手和一个高级玩家朋友预先组队）</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">第3步：确定匹配：</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*最终，系统会匹配10个大体上同水平、同等级的玩家，促成一个游戏。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*系统会尝试平衡这个队伍，尽量使双方的获胜机会都为50%。在绝大多数时间，误差会在3%之内&#8212;&#8212;类似50/50，49/51，48/52。实际上的获胜机会会有一点点差别（会在Q&amp;A里面回答这个问题），但是我们的研究标明，在绝大多数情况下，这实际上是一个非常精确的预测。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">长期来讲，我的匹配分（Elo</strong><strong style="word-wrap: break-word">值）是如何被测量的？</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">我们使用了一个修改过的ELO系统。ELO系统的基本要点通过使用数学比较两个人的积分，来预测两人的比赛结果&#8212;&#8212;类似&#8220;A和B比赛数局，A会赢掉75%的局&#8221;。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">然后，比赛结果出来了。如果你赢了，你会加分，如果你输了，你会被扣分。如果你是&#8220;出人意料&#8221;的赢了（系统认为你输的可能性更大），你会赢得更多的分数。额外的，如果你是一个新玩家，你会加分减分更快，以便于你可以快速的进入到你的水平等级。长期来看，这意味着好的玩家会得到高的匹配分，因为他们总是超过系统的预期，他们会不断加分直到系统可以正确的预测他们的胜率。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">我们修改这个系统给团队比赛使用，基本概念是：基于该团队的所有玩家，得到一个团队ELO值。如果你的队伍胜利，系统会假设该队伍的所有玩家都要比系统猜测的&#8220;更强&#8221;，并且加分。虽然有一些问题，但是总体上来讲是有效的，特别是玩家预先组队的时候。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">举例，本人在北美的服务器上有2000的普通匹配模式elo。如果我建一个小号，就算没有天赋和符文，我打到8级的时候就已经有1800elo了。这个系统并不完美，但是确实能够让玩家快速的接近自己水平所在的位置。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">当你才开始玩的时候，我们也对ELO做一些微调，让你更快的进入你水平所在的位置。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*我们有大量的，有优先级的方法来鉴定一个玩家，相比一个标准的新玩家是否更有技巧，更猛。如果发现是的，我们会在幕后提高他的elo一个档次。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*我们同样也会分辨真的菜鸟新手。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*提升等级也会极大的提高你的elo值。这个也将帮助系统将30级满级的召唤师和低等级的召唤师区分开来</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">如果你想知道ELO系统的理论，以及更多细节，你可以看看这：</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><a style="word-wrap: break-word; color: #336699" href="http://en.wikipedia.org/wiki/Elo_rating_system" target="_blank">http://en.wikipedia.org/wiki/Elo_rating_system</a></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><a style="word-wrap: break-word; color: #336699" href="http://zh.wikipedia.org/wiki/ELO" target="_blank">http://zh.wikipedia.org/wiki/ELO</a></p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">呃，等等，你是怎么处理组队玩家 vs solo(</strong><strong style="word-wrap: break-word">单排)</strong><strong style="word-wrap: break-word">玩家的？</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">我们大多数情况下，会通过将5人组队的队伍匹配给另外一个5人组队的队伍来避免这种情况的发生（几乎是所有情况下）。</p><br style="word-wrap: break-word" /><br style="word-wrap: break-word" />对于&#8220;部分&#8221;组队，我们进行了大量的研究，发现优势并没有想象的那么大，所以我们也会把他们混到solo（单排）的玩家里。我们发现有大量的因素会影响到组队优势的大小：从预先组队的规模（比如2、3、4、5组队），到组队玩家的水平，到高玩带菜鸟的组合，到玩家水平不同而导致的情况不同，以及其他的一些必须考虑到的微妙因素。这个要比一些我们曾见过的点对点算法-将任意的统计数据杂糅在一起猜测分数-要可靠的多 <br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">发现这些优势，我们就知道对于预先组队的队伍，需要提高多少elo值，来达成一个公平的匹配，确定一个适当的，在数学上合理的调整。结果在有些情况下非常令人惊讶（同时会校正统计数据）。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">虽然我们不会给出精确的数值，因为这是商业机密，但是我们可以告诉您：</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*5人组队只是比5个路人稍强。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*部分组队只是比5个路人略强。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*菜鸟5人组队并不会带来太大的优势，但是高玩组队会有很大的优势。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*团队实力方差高的队伍，会比方差低的队伍更强。（方差简单来说，是在平均值相同的情况下反应各个元素的大小差异，方差大表示差异大，高方差的队伍类似高玩带低玩，低方差的队伍各个队员实力接近。）</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*这说明了大体上，高水平玩家的Carry作用（可以理解为带领或者大腿），比低水平玩家的送人头作用（feeder）要强力。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">好吧&#8230;</strong><strong style="word-wrap: break-word">那为什么要把预先组队的玩家和非组队玩家匹配到一起？</strong></p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">这是一些原因：</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*这会帮助系统更快的找到适合你的匹配分，让系统更快的给你公平的匹配。这个的工作原理是，如果你组队，会减低运气所带来的成分，如果你单排，你的队友的好坏将对你输赢的影响更大。如果你预先组队，你会和你水平差不多的玩家组成队伍，你随机遇到猛男/坑爹队友几率会更小。因为游戏的结果更多来自你和水平相近的朋友的表现，而不是随机因素，所以你的匹配分会更快的到达精确的值。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left">*我们希望玩家可以和自己的朋友一起玩，因为这样会让他们玩的更有乐趣。你也不可能为5v5的游戏设置单独的2人匹配池或者3人匹配池，你需要组合他们来让系统工作。我们选择包含5人组队，因为这非常有乐趣。如果我们以后有足够大的匹配池，我们可能会将5人组队和部分组队区分开来，但是数据告诉我们，这基本不会提升匹配的公平程度，两者的效果基本相同。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">其他一些常见的问题：</strong></p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>为什么不加入一些其他的细节，类似击杀数等等来确定我的匹配分？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>因为这是有偏差的，并且因为非常难以给击杀数这个数值来评分，你使用一个gank英雄的时候（类似老鼠和易大师），要杀多少人才能算是好的呢？而且这会让好的辅助玩家非常吃亏，因为他们的目的就不是拿人头，甚至会为了自己的Carry挡死。最后，玩家会为了刷数据，故意拖长游戏时间，然后拿大量farm对方的人头，而不是为了赢得比赛。我们尽量把测量玩家水平和激励玩家的机制放到努力取胜上面，我们避免了一些不必要的周边行为，而这些行为既没乐趣，还会扰乱匹配系统。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>我非常愤怒，因为匹配系统老给我坑爹队友（feeders，送人头的）。为什么不阻止这种情况发生？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>我们的确有试图阻止这种情况发生，但是如果你被匹配到一个明显很弱的玩家，这也说明匹配系统同时匹配给你了一个或者多个强力的玩家。根据我们的研究，我们发现Carry（大腿）对队伍的带领作用要比feeder（送人头，坑爹）的坑爹作用更强。原因是在LOL里，多次击杀同一个玩家的收益是会递减的，并不像其他的同类游戏。我们的分析标明，在平均elo相同的情况下，提高或者降低这个队伍的某个玩家的elo值100（其他玩家相应降低/提高以保持平均分相同），整个队伍的实力会提高约7点elo值。这也表明，LOL中Carry的作用要比feeder的作用更给力一些。确实，有时候你会因为匹配到feeder而输掉这一局比赛，但是那是因为你们队的Carry不够给力。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>这样的话，如果我连胜了数盘，我是不是会被匹配到一些完全不可战胜的对手？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>不全是。连胜导致你的匹配分会提高，你会不断遇到更强的对手&#8212;&#8212;但是我们并不是故意的让你的胜率保持在50%的，我们的目的只是为了系统能够正确的预测游戏结果。最终，你会达到你的极限，你将会大致保持50%的胜率。比平均水平高的玩家，往往胜率会比50%略高，因为比他们弱的玩家更多，比他们强的玩家更少。所以匹配时，往往会略微&#8220;向下匹配&#8221;。对于排位顶尖的高端玩家，他们经常会有90%的胜率。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>你们会如何设计固定的队伍？类似WOW的竞技场队伍？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>这是一个非常好的想法，并且让我们有机会设计出更好的匹配系统。我们迟早会做这个，并且使用我们开发的新方法。我们需要检验并且搞清楚你大体上有多强力（例如你的个人积分），同时允许你创建/解散队伍。这是个非常大的工程，但是我们对此非常有激情~</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>如果匹配系统真的那么公平，那为何我老遇见那种一边倒的比赛？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>有两个原因。第一，LOL有时候&#8220;雪球效应&#8221;会非常明显。前期太差的表现会导致游戏让人感觉非常一边倒。特别是某些队伍，如果他们开始很顺风，就会一直很顺风。我们遇到过同样的队伍，第一局25-5取胜，第2局确以类似的比分输掉。第二个原因是，玩家发挥的并不好，队伍选取阵容也不好。要进行一局势均力敌的比赛，你需要平衡玩家水平和平衡阵容的选取。有时候玩家选了一个比较渣的阵容，比如5个近战dps，或者3坦克2法师之类的，或者没选打野英雄而对面有。这样的话，尽管你的队伍实力也很不错，但是情况往往惨不忍睹。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>为什么我作为一个高等级玩家，有时候会匹配到一些低等级玩家？他们看上去都是来送人头的。</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>当一个高等级玩家和一个低等级玩家组队，这是一个非常令人头疼的问题。我们希望玩家可以和自己的朋友一起玩，并且希望这是一种愉快的体验。但是我们并不希望将一部分人的快乐建立在另一部分人的痛苦之上，所以我们往往将这种组合评分更高，保护新玩家不会被高等级玩家虐待。非常不幸的是，不管我们怎么做，我们把这样的组合匹配到任何的游戏中，都有可能造成不愉快的体验。因此，我们计划将实施一个&#8220;不平衡组队&#8221;的队列，类似我们尽量将5人组队匹配给5人组队。</p><br style="background-color: #ffffff; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444" /><br style="word-wrap: break-word" />
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">Q</strong><strong style="word-wrap: break-word">：</strong>我20级了，然后我被匹配到了一些10级的和一些29级的，怎么回事？</p>
<p style="padding-bottom: 0px; background-color: #ffffff; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Tahoma, 'Microsoft Yahei', Simsun; word-wrap: break-word; color: #444444; padding-top: 0px" align="left"><strong style="word-wrap: break-word">A</strong><strong style="word-wrap: break-word">：</strong>当不同等级的玩家组队，我们会使用他们的平均等级来作为匹配的参考。等级并不是匹配系统的主导参数&#8212;&#8212;匹配系统通常是使用实力来匹配&#8212;&#8212;但是我们也会尽量将等级相近的玩家匹配到一起。在预先组队的情况下，我们没法替玩家选择，所以我们尽我们所能，使用平均等级。我们会在这个计算系统里把30级的玩家看作36级，所以我们通常能让中等级玩家的游戏没有30级玩家，然而有时候呢，29级玩家能插进来。</p><img src ="http://www.cppblog.com/ming81/aggbug/195185.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-11-14 11:07 <a href="http://www.cppblog.com/ming81/archive/2012/11/14/195185.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)游戏对象的实现 </title><link>http://www.cppblog.com/ming81/archive/2012/09/06/189698.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Thu, 06 Sep 2012 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/09/06/189698.html</guid><description><![CDATA[大部分的MMOG中，游戏对象的类型都大同小异，主要有物品、生物、玩家等。比如在wow中，通过服务器发下来的GUID我们可以了解到，游戏中有9大类对象，包括物品(Item)、背包(Container)、生物(Unit)、玩家(Player)、游戏对象(GameObject)、动态对象(DynamicObject)、尸体(Corpse)等。 
<p>　　在mangos的实现中，对象使用类继承的方式，由Object基类定义游戏对象的公有接口及属性，包括GUID的生成及管理、构造及更新UpdateData数据的虚接口、设置及获取对象属性集的方法等。然后分出了两类派生对象，一是Item，另一是WorldObject。Item即物品对象，WorldObject顾名思义，为世界对象，即可添加到游戏世界场景中的对象，该对象类型定义了纯虚接口，也就是不可被实例化，主要是在Object对象的基础上又添加了坐标设置或获取的相关接口。</p>
<p>　　Item类型又派兵出了一类Bag对象，这是一种特殊的物品对象，其本身具有物品的所有属性及方法，但又可作为新的容器类型，并具有自己特有的属性和方法，所以实现上采用了派生。mangos在实现时对Bag的类型定义做了点小技巧，Item的类型为2，Bag的类型为6，这样在通过位的方式来表示类型时，Bag类型也就同时属于Item类型了。虽然只是很小的一个技巧，但在很多地方却带来了极大的便利。</p>
<p>　　从WorldObject派生出的类型就有好几种了，Unit、GameObject、DynamicObject和Corpse。Unit为所有生物类型的基类，同WorldObject一样，也不可被实例化。它定义了生物类型的公有属性，如种族、职业、性别、生命、魔法等，另外还提供了相关的一些操作接口。游戏中实际的生物对象类型为Creature，从Unit派生，另外还有一类派生对象Player为玩家对象。Player与Creature在实现上最大的区别是玩家的操作由客户端发来的消息驱动，而Creature的控制是由自己定义的AI对象来驱动，另外Player内部还包括了很多的逻辑系统实现。</p>
<p>　　另外还有两类特殊的Creature，Pet和Totem，其对象类型仍然还是生物类，只是实现上与会有些特殊的东西需要处理，所以在mangos中将其作为独立的派生类，只是实现上的一点处理。另外在GameObject中也实现有派生对象，最终的继承关系图比较简单，就不麻烦地去画图了。</p>
<p>　　从我所了解的早期游戏实现来看，大部分的游戏对象结构都是采用的类似这种方式。可能与早期对面向对象的理解有关，当面向对象的概念刚出来时，大家认为继承就是面向对象的全部，所以处处皆对象，处处皆继承。</p>
<p>　　类实现的是一种封装，虽然从云风那里出来的弃C++而转投C的声音可能会影响一部分人，但是，使用什么语言本身就是个人喜好及团队整体情况决定的。我们所要的也是最终的实现结果，至于中间的步骤，完全看个人。还是用云风的话说，这只是一种信仰问题，我依然采用我所熟悉的C++，下面的描述也是如此。</p>
<p>　　随着面向对象技术的深入，以及泛型等概念的相继提出，软件程序结构方面的趋势也有了很大改变。C++大师们常说的话中有一句是这样说的，尽是采用组合而不是继承。游戏对象的实现也有类似的转变，趋向于以组合的方式来实现游戏对象类型，也就是实现一个通用的entity类型，然后以脚本定义的方式组合出不同的实际游戏对象类型。</p>
<p>　　描述的有些抽象，具体实现下一篇来仔细探讨下。<br /><br /><br />在游戏编程精粹四有三篇文章讲到了实体以及实体管理的实现方案，其中一篇文章说到了实体管理系统的四大要素：定义实体怎样沟通的实体消息，实现一实体类代码和数据的实体代码，维护已经注册在案的实体类列表，和用来创建、管理、发送消息的实体管理器。</p>
<p>　　关于实体消息的内容之前讨论事件机制的时候做过一点说明，其实这也就是按接口调用和按消息驱动的区别，现在mangos的做法是完全的接口调用，所以引擎内部就没有任何的实体消息。实体代码实现和实体管理器是我们重点要讨论的内容。</p>
<p>　　另有一篇文章也提到了使用类继续的方式实现游戏对象的两大问题，一是它要求系统中的所有对象都必须从一个起点衍生而成，也就是说所有对象类在编译的时候已经确定，这可能是一个不受欢迎的限制，如果开发者决定添加新的对象类，则必须要对基类有所了解，方能支持新类。另一个问题在于所有的对象类都必须实现同样的一些底层函数。</p>
<p>　　对于第二个问题，可以通过接口继承的方式来避免基类的方法太多。在mangos的实现中就采用了类似的方法，从Object虚基类派生的Unit和WorldObject仍然还是不可实例化的类，这两种对象定义了不同的属性和方法，分来实现不同类型的对象。在游戏内部可以根据对象的实际类型来Object指针向下转型为Unit或WorldObject，以调用需要的接口。方法虽然不够OO，也还能解决问题。但是第一个问题是始终无法避免的。</p>
<p>　　所以我们便有了通用实体这么一个概念，其主要方法是将原来基类的接口进行分类，分到一个个不同的子类中，然后以对象组合的方式来生成我们所需要的实际游戏对象类型。这个组合的过程可以通过脚本定义的方式，这样便可以在运行时生成为同的对象类型，也就解决了上面提到的第一个问题。</p>
<p>　　通用实体的实现方法在目前的游戏引擎及开源代码中也可以看到影子。一个是BigWorld，从提供的资料来看，其引擎只提供了一个entity游戏对象，然后由游戏内容实现者通过xml和python脚本来自由定义不同类型的entity类型，每种类型可有不同的property和不同的方法。这样原来由基类定义的接口完全转移到脚本定义，具有非常强的灵活性。</p>
<p>　　另外还有一个是CEL中的entity实现。按照CEL的描述，entity可以是游戏中的任意对象，包括玩家可交互的对象，如钥匙、武器等，也可以包括不能直接交互的对象，如游戏世界，甚至任务链中的一部分等。entity本身并没有任何特性，具体的功能实现需要靠附加property来完成。简单来说，property才定义了entity可以做什么，至于该怎么做，那又是依靠behavior来定义。所以，最终在CEL中一个游戏对象其实是由entity组合了多个property及多个behavior而生成的。</p>
<p>　　但是CEL中的property与BigWorld中的property意义不大一样，在CEL中可定义的property其实是引擎内部要先提供的，比如其示例中所举的pcobject.mesh、pcmove.linear、pctools.inventory等，而BigWorld中的property是完全的自由定制。从这个角度来讲，其实可以把CEL中的property看作是游戏的逻辑系统，也就是我们上面所描述的，接口分类后所定义的子类。</p>
<p>　　由引擎内部提供可选择的property与BigWorld所采用的完全自由定制property其实本质上是相同的。在用BigWorld实现的游戏中，也不可能为每种游戏对象类型都完全从头定义property，基于代码利用的原则，也会先定义一些小类，然后在entity类型定义时以自定义property的方式来包含这些小类。当然，我没有使用过BigWorld，上面的描述也只是基于游戏实现的大原则所做出来的。</p>
<p>　　描述的依然有些抽象，我们可以用wow及mangos代码来说明一下。mangos中为object定义了一个属性集合，根据对象类型的不同，这个属性集的大小及保存数据也会有差异，另外游戏对象内部含有处理不同游戏逻辑的系统，如RestSystem、FloodFilterSystem、VariousSystem等等，在player.h中以接口组的方式进行定义。</p>
<p>　　如果要将这种结构改为我们描述的通用entity系统，可以让object只提供property注册和删除的接口，这里的property定义与CEL中的相同，放在mangos中也就是上面说的RestSystem、FloodFilterSystem、VariousSystem这些。然后也通过xml文件的方式定义我们所需要的游戏对象类型，如player,creature,item等，不同的对象类型可以选择加载不同的property，加载的原则是需要哪些功能就加载哪些property。</p>
<p>　　对象的定义按上面的方法完成后，对象的实现也需要做一些修改。以前客户端的消息是直接交由player来处理，AI也是直接调用creature的接口来完成一些功能，现在通用的entity内部已经没有任何可用的方法，所有的实现都转到了property中，所以需要由各个property实现自己来注册感兴趣的事件及消息，entity实现一个消息的转发，转给对此感兴趣的property来处理。其余的实现就没有什么不同了。</p>
<p>　　当然，我们再做一点扩展，让property不光由引擎来提供，用脚本本身也能定义property，并且可以通过xml来注册这些property，这样便实现了与BigWorld一样的完全自由特性。这其实也就是将很多用C++实现的功能转移到了python中，这种做法可作为参考，但不一定对所有人合适，至少在我看来，这样的实现也基本只能由程序员来做，所以让程序员选择自己最擅长的语言可能会更易于开发和调试。</p>
<p>有关游戏对象实现的描述，前面两篇文章中说的不甚清楚，主要是一直都要引用网上能够找到的资料来进行描述，以避免与公司引起不必要的麻烦。所以语言有些拼凑的感觉，举的例子也很不恰当，今天正好看到了游戏编程精粹五和六上的两篇文章，内容都差不多，&lt;&lt;基于组件的对象管理&gt;&gt;和&lt;&lt;基于组件的游戏对象系统&gt;&gt;，说的也是我上两篇文章想要描述的内容，所以再补一篇，引用其中的部分文字进行明确的说明。</p>
<p>&nbsp;</p>
<p>　　传统的游戏对象管理系统采用继承的方式来实现，例如，所有的子类都从CObject派生。大多数情况下，直接派生的也是抽象类，其中带一些功能而另一些子类则不带这些功能，比如可控制/不可控制，可动画/不可动画等。mangos的实现中基本就是这种情况，从Object直接派生的Unit和WorldObject都是不可直接实例化的类。</p>
<p>　　传统方法的问题在于无法应对需求的变化，如要求武器也有动画效果时就无法处理了。如果硬要是这样做，那随着需求的啬，很多的方法会被放到基类中，最终的结果是继承树变得越来越头重脚轻，这样的类会丧失它的内聚性，因为它们试图为所有对象完成所有的事。</p>
<p>　　就是说到最后，基类会有一个很长的接口列表，而很多的游戏对象类型根本不需要实现其中的一些甚至大部分接口，但是按照这种结构却又必须去实现。以至于于实现一个非常庞大的对象，而且想要修改一点功能会导致系统的大调整。</p>
<p>　　我们希望的系统是可以将现有的功能组合到新的对象中，并且在将新的功能添加到现有的对象中时不需要重构大量的代码和调整继承树的结构。</p>
<p>　　实现的方法就是从组件来创建一个对象。组件是一个包含所有相关数据成员和方法的类，它完成某个特定的任务。把几个组件组合在一起就可以创建一个新的对象。如把Entity组件、Render组件和Collectable组件组合在一起生成了一个Spoon对象。Entity组件让我们可以把对象放到游戏世界中，Render组件让我们可以为对象指定一个模型进行渲染，而Collectable组件让我们可以拾取这个对象。</p>
<p>　　关于组件的实现，所有的组件都从一个基础组件接口派生，可称其为IComponent。每个组件也有自己的接口定义，并且这个接口也需要从IComponent派生，类似于这样：IComponent -- ICmpRender -- CCmpRender</p>
<p>　　这里的每个组件也就是我在上一篇中所说的由引擎提供的属性，或者说在BigWorld中自己实现然后定义的属性，或者使用mangos中的定义，就是一个个的System，虽然mangos并没有将其完全做成组件，但是通过其代码注释可以看到，接口也是按功能组进行了分类，如果要拆分成组件也是比较方便的。</p>
<p>　　组件之间的通信有两种方法，一是用组件ID查询到组件接口指针，然后调用接口方法；二是使用消息的方式，向对象中所有组件发消息。在初始化的时候，每一个组件类型都会告诉对象管理器应该接收什么样的消息。</p>
<p>　　查询接口的方法也就是直接的方法调用，只不过接口不是全部在基类中，所以必须先查询到指定的组件然后才能调用其接口。消息的使用前面已经说过多次，其实现方案也有过说明。</p>
<p>　　最后是关于游戏对象功能的扩展和游戏对象的定义。需要扩展功能也就是需要实现一个新的组件，或者修改现在组件。在大多数情况下，扩展都不会引起结构的很大调整，受影响的最多只是使用到该组件的部分代码。</p>
<p>　　游戏对象定义可采用完全数据驱动的方式，使用xml或者脚本语言来定义对象类型，以及每个类型需要加载的组件。对象类型注册到对象管理器后，由管理器提供创建指定类型的对象的方法。数据驱动的方式能够让策划自由定义游戏对象类型，并且随时可自由创建新的对象类型。</p><img src ="http://www.cppblog.com/ming81/aggbug/189698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-09-06 14:26 <a href="http://www.cppblog.com/ming81/archive/2012/09/06/189698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos服务器的游戏对象和AI系统(三)</title><link>http://www.cppblog.com/ming81/archive/2012/08/28/188529.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 28 Aug 2012 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/08/28/188529.html</guid><description><![CDATA[<p><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">PetAI</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">::</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">MoveInLineOfSight</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">)</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//有单位进入宠物视野</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">if</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">( !</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">getVictim</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() &amp;&amp; </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GetCharmInfo</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() &amp;&amp;</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GetCharmInfo</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">()-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">HasReactState</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">REACT_AGGRESSIVE</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) &amp;&amp;</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">isTargetableForAttack</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() &amp;&amp; </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">IsHostileTo</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">( </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> ) &amp;&amp;</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">isInAccessablePlaceFor</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">))</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//好多判断：不是我已有的攻击目标，并且我是攻击性的，并且我可以攻击此单位，并且单位是我的敌对方，并且我能够得着它</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">attackRadius</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> = </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GetAttackDistance</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">if</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">IsWithinDistInMap</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">attackRadius</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) &amp;&amp; </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GetDistanceZ</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) &lt;= </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">CREATURE_Z_ATTACK_RANGE</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">)</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//在我的攻击范围内</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">if</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">IsWithinLOSInMap</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">))</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//在我的视野中</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">AttackStart</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//攻击开始消息</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">RemoveSpellsCausingAura</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SPELL_AURA_MOD_STEALTH</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//去掉我的有隐身状态（有的话）</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">下面看看AttackStart干了什么：</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">PetAI</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">::</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">AttackStart</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">)</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">if</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(!</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> || (</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">isPet</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() &amp;&amp; ((</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Pet</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*)</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">)-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">getPetType</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() == </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">MINI_PET</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">))</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//一些保护</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">return</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">;</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">if</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Attack</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">,</span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">true</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">))</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//攻击成功</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">{</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">clearUnitState</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">UNIT_STAT_FOLLOW</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//清除我的跟随状态</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GetMotionMaster</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">()-&gt;</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">MoveChase</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">u</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt; font-weight: bold">//通过MotionMaster修改移动类型为Chase，并开始追。MotionMaster的分析见下面</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">inCombat</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> = </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">true</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">;</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">}</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(0,0,0); font-size: 14pt">四、MotionMaster</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 12pt">在Unit类中还有个MotionMaster成员，Creature在初始化AI的时候，对MotionMaster进行初始化。MotionMaster维护一个移动的列表并负责不同移动类型的生成。具体的移动类型控制Creature的移动。</span><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 12pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 12pt">下面是MotionMaster生成不同移动类型的接口函数：</span><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 12pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveIdle</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">();</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveTargetedHome</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">();</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveFollow</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">target</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">dist</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">angle</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveChase</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">target</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">dist</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> = 0.0f, </span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">angle</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> = 0.0f);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveConfused</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">();</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveFleeing</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">enemy</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">time</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> = 0);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MovePoint</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">id</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">x</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">,</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">y</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">,</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">z</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveSeekAssistance</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">x</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">,</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">y</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">,</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">float</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">z</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveSeekAssistanceDistract</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">timer</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveTaxiFlight</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">path</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">pathnode</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MoveDistract</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">time</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 12pt">Mangos对移动进行了单独的处理，这个是它的一个亮点和优点。</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 12pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(0,0,0); font-size: 14pt">五、结论</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">1. 网游服务器AI的基本结构还是体现出来了，一个网游服务器AI系统确实主要是由游戏对象、AI和移动组成；</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">2. 关键类设计得过于复杂，需要进一步细化和模块化；像Unit和Player里面的战斗和技能很必要作为一个独立模块来设计和实现。Creature和Player等复杂的类，需要划分出状态，否则太多状态变量和条件判断，很容易出错，而且不容易修改和扩充。</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">3. 代码复杂度比较高，一般程序员难于驾驭；如有人员替换，维护和修改比较困难；</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">4. 无内存池和对象池，大量使用new和delete。长时间运行后，服务器效率是个问题；</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">5. 重用性很差，很难在上面搞出个其它不是&#8220;WOW&#8221;的游戏。听说国内有公司打算用Mangos搞其它网游，肯定修改不动，不了了之。</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal">Mangos确实只是一个爱好和兴趣的产物，并不适合实际的商业网络游戏。新手学习有一定的参考，但是参考价值不大，因为门槛还是比较高的（如巨大的类、实现地图区块广播的模板技术），新手额外要花不少代价。对新手来说，我更建议看一些韩派或国内网游的实现。但是Mangos毕竟把WOW给模拟出来了，我对Mangos的开发者们的付出和工作量还是表示敬意。</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p></span><img src ="http://www.cppblog.com/ming81/aggbug/188529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-08-28 15:09 <a href="http://www.cppblog.com/ming81/archive/2012/08/28/188529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos服务器的游戏对象和AI系统(二)</title><link>http://www.cppblog.com/ming81/archive/2012/08/28/188527.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 28 Aug 2012 07:03:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/08/28/188527.html</guid><description><![CDATA[<p><span style="font-family: '宋体'; color: rgb(0,0,0); font-size: 14pt">三、CreatureAI</span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal"></span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p>
<p>&nbsp;</p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 7.5pt"></span><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"></span></p><span style="font-family: 'Microsoft Yahei'; color: rgb(0,0,0); font-size: 10.5pt"><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt; font-weight: normal"><font size="2" face="宋体"></font></span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 10.5pt">
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">CreatureAI这个类并不大，构造函数要传</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">入</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">一个Creature的指针，然后就是20来个接口函数。</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">构造函数：</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">explicit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">CreatureAI</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) : </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">m_creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt; font-weight: normal">接口函数不多，可以全部列出来：</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">MoveInLineOfSight</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">EnterCombat</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*enemy*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called for reaction at stopping attack at no attackers or targets</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">EnterEvadeMode</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at reaching home after evade</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">JustReachedHome</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at any heal cast/item used (call non implemented)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">HealBy</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> * </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*healer*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*amount_healed*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at any Damage to any victim (before damage apply)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">DamageDeal</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> * </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*done_to*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> &amp; </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*damage*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at any Damage from any attacker (before damage apply)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Note: it for recalculation damage or special reaction at damage</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">DamageTaken</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> * </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*done_by*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> &amp; </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*damage*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when the creature is killed</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">JustDied</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when the creature kills a unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">KilledUnit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when the creature summon successfully other creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">JustSummoned</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* ) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SummonedCreatureDespawn</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Creature</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*unit*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when hit by a spell</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SpellHit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*, </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">const</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SpellEntry</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when spell hits creature's target</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SpellHitTarget</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*, </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">const</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SpellEntry</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">AttackedBy</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">attacker</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">);</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when creature is spawned or respawned (for reseting variables)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">JustRespawned</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">() {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at waypoint reached or point movement finished</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">MovementInform</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*MovementType*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*Data*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at text emote receive from player</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">ReceiveEmote</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Player</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">* </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*pPlayer*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">, </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*text_emote*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when creature attack expected (if creature can and no have current victim)</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Note: for reaction at hostile action must be called AttackedBy function.</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">AttackStart</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *) {}</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Is unit visible for MoveInLineOfSight</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">bool</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">IsVisible</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> *) </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">const</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> { </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">return</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">false</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">; }</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called when victim entered water and creature can not enter water</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">bool</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">canReachByRangeAttack</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Unit</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">*) { </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">return</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">false</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">; }</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">// Called at World update tick</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">virtual</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">void</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">UpdateAI</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">(</span><span style="font-family: '新宋体'; color: rgb(0,0,255); font-size: 9pt">const</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">uint32</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(0,128,0); font-size: 9pt">/*diff*/</span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt">) {}</span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span>可以看到，大部分接口是事件触发和消息通知。UpdateAI我放到最后，这个和别的接口函数不同，是负责AI状态的更新处理。</span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span>以CreatureAI为基类，派生出了PetAI、CreatureEventAI、GuardAI、ReactorAI、AggressAI、TotemAI和NullCreatureAI 7类基本AI。Creature的AIM_Initialize()函数，对AI进行初始化，根据Creature的类型选择不同的AI。值得提出的是，Mangos还支持ScriptAI，对于非宠物类的生物支持扩展脚本AI。Mangos的脚本系统我还没有怎么看，有空研究下。</span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span>可以看到Mangos的AI设计还是比较传统的，Creature类相当于身体和物理存在，干很多&#8220;傻大粗&#8221;的事情；AI相当于Creature的大脑，对事件进行响应和处理，指挥着身体物理存在进行反应。</span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span>下面可以看下宠物AI的一段代码：</span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"><font size="2"></font></span>
<p><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span><span style="font-family: '新宋体'; color: rgb(0,0,0); font-size: 9pt"></span></p></span></span><img src ="http://www.cppblog.com/ming81/aggbug/188527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-08-28 15:03 <a href="http://www.cppblog.com/ming81/archive/2012/08/28/188527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos服务器的游戏对象和AI系统(一)</title><link>http://www.cppblog.com/ming81/archive/2012/08/28/188524.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 28 Aug 2012 06:24:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/08/28/188524.html</guid><description><![CDATA[<p><span style="font-family: '宋体'; font-size: 14pt">主要的几个对象类</span><span style="font-family: '宋体'; font-size: 14pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">1．</span><span style="font-family: '宋体'; font-size: 10.5pt">Object<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">1) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">InWorld</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">判断和操作</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">2) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">GUID</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Mangos的每个对象都有唯一的GUID，每类GUID的最大值是保存在数据库中，初始化时候从数据库加载。Mangos这样做还是很奢侈的，国内服务器可能都存在合服需求，所以国内服务器操持角色ID不同即可。可能要合服的服务器在开服的时候要把的角色ID范围要规划好(天龙八部的角色ID的最大值是保存在数据库中的)。国内服务器中对于重要物品、宠物可能需要唯一的ID，可以考虑角色ID + 物品、宠物id来实现。uint32应该够用了，但是也要限制重要物品的种类和数量。</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">3) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Object类型</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">TypeId</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 7.5pt">enum</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TypeID</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt">{</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_OBJECT</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 0,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_ITEM</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 1,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_CONTAINER</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 2,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_UNIT</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 3,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_PLAYER</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 4,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_GAMEOBJECT</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 5,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_DYNAMICOBJECT</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 6,</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">TYPEID_CORPSE</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> = 7</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt">};</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 7.5pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">4) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">网络包发送</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SendUpdateToPlayer</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">5) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">基本状态组包</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Values</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">、</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">OutOfRange</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">、</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Movement</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"> </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">UpdateBlock</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">等</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">6) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Int, UInt, float等标记</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">数据设置、加载、访问</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Get</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">/SetXXX</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">Value</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">、</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">SetFlag</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 7.5pt">union</span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt">{</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">int32</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> *</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">m_int32Values</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt">;</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">uint32</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> *</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">m_uint32Values</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt">;</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span><span style="font-family: 'Times New Roman'; color: rgb(0,0,255); font-size: 7.5pt">float</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"> *</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 7.5pt">m_floatValues</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt">;</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 7.5pt">};</span><span style="font-family: 'Times New Roman'; font-size: 7.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt"></span><span style="font-family: '新宋体'; font-size: 9pt">Object有很多数据、状态以数组形式存储，访问时候通过类型和标记定位。</span><span style="font-family: '新宋体'; font-size: 9pt"></span></p>
<p><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">7) </span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">任务判断接口</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt">hasQuest</span><span style="font-family: '新宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">2．</span><span style="font-family: '宋体'; font-size: 10.5pt">Item<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">创建和复制</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Create</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">/Clone</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Item</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">所有者Owner(Player)</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">数据库存取</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SaveTo/LoadFromDB</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Mangos的每个Item在数据中是作为一条记录保存的，一般国内网游是打包保存在玩家记录里面，国内网游的做法在数据库效率上要高很多。</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">绑定</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Binding</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、损坏</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Broken</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、是否可交易</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">CanBeTrade</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、叠放数量、是否装备等一般道具属性</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">5) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">在包中的位置</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Bag、Slot</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">6) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">增强状态和时效</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Enhancement</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">7) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Timer</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">更新</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">8) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">状态更新和广播</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">State</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">9) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">技能和魔法相关</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Skill/Spell</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">10) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">任务相关</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">hasQuest</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">3．</span><span style="font-family: '宋体'; font-size: 10.5pt">Bag<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">增加、删除、得到某位置的道具Store/RemoveItem</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">空间IsEmpty、GetFreeSlots</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">数据库存取SaveTo/LoadFromDB</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">组包更新</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">BuildCreateUpdateBlockForPlayer</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">4．</span><span style="font-family: '宋体'; font-size: 10.5pt">WorldObject<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">位置和朝向</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Relocate</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SetOrientation</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">附近空间位置</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetClosePoint</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">所在地图、区域和地区</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetMapId</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetZoneId</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetAreaId</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">名字</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetName</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">5) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">和其它WorldObject位置、角度等关系</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">IsWithinDist</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">IsInRange</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">6) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">发送网络消息</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SendMessageToSet</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">7) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">发送聊天、喊叫等消息</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">MonsterSay</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">MonsterYellToZone</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">8) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">对玩家来说是否可见</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">isVisibleFor</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">9) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">召唤Creature，</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SummonCreature</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">5．</span><span style="font-family: '宋体'; font-size: 10.5pt">Unit<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 9pt">Unit<font face="宋体">类是很复杂的一个类，改类具有很多属性和方法，实现了游戏中</font><font face="Times New Roman">Player</font><font face="宋体">，</font><font face="Times New Roman">Creature</font><font face="宋体">等主要功能。</font></span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">渐变状态</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetDiminishing</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">战斗相关（计时器、攻击对象、停止等）</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">setAttackTimer</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Attack</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">getVictim</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SendMeleeAttackStop</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">单元状态</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">addUnitState</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">等级、种族、职业、装甲、血量、伤害能力等属性</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">getLevel</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">getGender</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">getRace</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetArmor</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetHealth</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetPower</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">5) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">友好、敌对等阵营关系</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">IsHostileTo</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">IsFriendlyTo</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">6) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">站立、行走、骑乘、战斗、飞行、水下、恐惧、死亡等状态</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">getStandState</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">IsMounted</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">DeathState</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">7) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">技能和伤害处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">DealDamage</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">MeleeSpellHitResult</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetWeaponSkillValue</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">8) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">类型（商店、银行、飞行点、行会、拍卖行等）</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">isVendor</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">isBanker</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">9) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">施展法术</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">CastSpell</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">10) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">光环状态和特效以及数值影响</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">HasAura</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">RemoveAura</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">11) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">广播伤害、攻击状态等消息</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SendAttackStateUpdate</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SendSpellMiss</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">12) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">主人、召唤者、宠物等信息</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetOwnerGUID</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">SetCharmerGUID</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">、</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetPet</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">13) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">状态更新广播</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">stat system</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">14) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">可见性处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Visibility system</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">15) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">威胁值处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Threat related methods</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">16) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">DynamicObject</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">对象和</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GameObject</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">对象的附加</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">GetDynObject</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">17) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">event处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">m_Events</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">18) </span><span style="font-family: 'Times New Roman'; color: rgb(1,0,1); font-size: 9pt">MotionMaster</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 9pt">Unit<font face="宋体">类设计得过大，还包含了战斗、技能、伤害处理、光环状态影响等这些比较复杂的功能模块。</font></span><span style="font-family: '宋体'; color: rgb(1,0,1); font-size: 9pt"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">6．</span><span style="font-family: '宋体'; font-size: 10.5pt">Creature<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">加入到世界</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">加载装备</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">数据库存取</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">类型，是否是车辆、宠物、图腾、精英等</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">5) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">能力，能否行走、游泳、飞行</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">6) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">对技能免疫</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">7) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">AI和脚本</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">8) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">售卖的道具</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">9) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">状态更新</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">10) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">对话内容</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">11) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">聊天、喊叫</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">12) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">战斗行为，寻求帮助</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">13) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">重生处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">14) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">任务相关</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: 'Times New Roman'; font-size: 10.5pt">7．</span><span style="font-family: '宋体'; font-size: 10.5pt">Player<font face="宋体">类主要功能</font></span><span style="font-family: '宋体'; font-size: 10.5pt"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">1) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">加入到世界</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">2) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">传送</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">3) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">更新</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">4) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">社会关系</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">5) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">飞机</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">6) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">位置</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">7) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">宠物</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">8) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">聊天</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">9) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">装备、背包和仓库</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">10) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">增强状态</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">11) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">完整的任务处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">12) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">数据库存取</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">13) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">邮件</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">14) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">技能</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">15) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">天赋</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">16) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">声望</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">17) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">战场</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">18) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">战斗状态和模式更新</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">19) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">竞技场</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">20) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">移动处理</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">21) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">副本</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">22) </span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">组队</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">Player类是继Unit类后另外一个很大的类，实现和很多功能。我现在很佩服Mangos服务器的程序员的水平了，这么多功能，居然一个类搞定。这样的代码对后继维护和修改者绝对是噩梦。</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p>
<p><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal">其它类比较小，略过。</span><span style="font-family: '新宋体'; font-size: 9pt; font-weight: normal"></span></p><img src ="http://www.cppblog.com/ming81/aggbug/188524.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-08-28 14:24 <a href="http://www.cppblog.com/ming81/archive/2012/08/28/188524.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)MaNGOS-Zero源码学习之mangosd游戏逻辑服务器（二）：socket的处理方式 </title><link>http://www.cppblog.com/ming81/archive/2012/07/25/185024.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 25 Jul 2012 06:49:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/25/185024.html</guid><description><![CDATA[本篇将介绍客户端与游戏逻辑服务器连接建立以后，mangosd如何接收、解析和处理客户端发过来的协议。本篇不再讨论mangosd与客户端的认证及建立最终RC4流加密的过程，想了解这部分内容请看该系列的<span style="text-decoration: underline"><a href="http://www.cppblog.com/ming81/archive/2012/07/25/185023.html"><font color="#6466b3">第一篇</font></a></span>。 
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><strong><font size="3">一、acceptor socket的监听启动及注册</font></strong></span></p>
<p>mangosd的main ()函数调用单例对象sMaster的Run ()函数，启动监听socket的代码如下：</p>
<p>&nbsp;</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> Master::Run()</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #008000">///- Launch the world listener socket</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     uint16 wsport = sWorld.getConfig (CONFIG_UINT32_PORT_WORLD);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     std::string bind_ip = sConfig.GetStringDefault (<span style="color: #006080">"BindIP"</span>, <span style="color: #006080">"0.0.0.0"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     <span style="color: #0000ff">if</span> (sWorldSocketMgr-&gt;StartNetwork (wsport, bind_ip) == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>         sLog.outError (<span style="color: #006080">"Failed to start network"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>         Log::WaitBeforeContinueIfNeed();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>         World::StopNow(ERROR_EXIT_CODE);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>         <span style="color: #008000">// go down and shutdown the server</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>     sWorldSocketMgr-&gt;Wait ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span> }</pre><!--CRLF--></div></div>
<p>&nbsp;</p>
<p>mangosd用WorldSocketMgr类来管理socket。StartNetwork ()会调用StartReactiveIO ()来启动监听socket，处理代码如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, <span style="color: #0000ff">const</span> <span style="color: #0000ff">char</span>* address)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #008000">//（1）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     m_NetThreadsCount = <span style="color: #0000ff">static_cast</span>&lt;size_t&gt; (num_threads + 1);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     m_NetThreads = <span style="color: #0000ff">new</span> ReactorRunnable[m_NetThreadsCount];</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     <span style="color: #008000">// -1 means use default</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     m_SockOutKBuff = sConfig.GetIntDefault (<span style="color: #006080">"Network.OutKBuff"</span>, -1);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     m_SockOutUBuff = sConfig.GetIntDefault (<span style="color: #006080">"Network.OutUBuff"</span>, 65536);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>     <span style="color: #0000ff">if</span> ( m_SockOutUBuff &lt;= 0 )</pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>         sLog.outError (<span style="color: #006080">"Network.OutUBuff is wrong in your config file"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>     <span style="color: #008000">//（2）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>     WorldSocket::Acceptor *acc = <span style="color: #0000ff">new</span> WorldSocket::Acceptor;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span>     m_Acceptor = acc;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum21">  21:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum22">  22:</span>     ACE_INET_Addr listen_addr (port, address);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum23">  23:</span>     <span style="color: #0000ff">if</span> (acc-&gt;open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum24">  24:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum25">  25:</span>         sLog.outError (<span style="color: #006080">"Failed to open acceptor ,check if the port is free"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum26">  26:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum27">  27:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum28">  28:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum29">  29:</span>     <span style="color: #008000">//（3）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum30">  30:</span>     <span style="color: #0000ff">for</span> (size_t i = 0; i &lt; m_NetThreadsCount; ++i)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum31">  31:</span>         m_NetThreads[i].Start ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum32">  32:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum33">  33:</span>     <span style="color: #0000ff">return</span> 0;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum34">  34:</span> }</pre><!--CRLF--></div></div>
<p>（1）ReactorRunnable类继承了ACE_Task_Base，ACE_Task_Base 是ACE 中的任务或主动对象&#8220;处理结构&#8221;的基类。在ACE 中使用了此类来实现主动对象模式。所有希望成为&#8220;主动对象&#8221;的对象都必须从此类派生。可以把ACE_TASK 看作是更高级的、更为面向对象的线程类[1]。ACE_Task_Base调用时继承类必须重写svc方法，并且在使用时保证调用了activate ()方法。</p>
<p>（2）指定监听地址，端口并把Acceptor绑定到第一个线程的Reactor上。启动Acceptor开始监听网络IO。</p>
<p>（3）启动所有线程，每个线程上有一个单独的ACE_Reactor* m_Reactor;，这里的Reactor使用的是多线程的ACE_TP_Reactor。可以各自单独完成事件的多路复用。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><strong><font size="3">二、线程体函数</font></strong></span></p>
<p>线程体函数ReactorRunnable::svc () 如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">virtual</span> <span style="color: #0000ff">int</span> svc ()</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #008000">//（1）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     WorldDatabase.ThreadStart ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     </pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     SocketSet::iterator i, t;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #0000ff">while</span> (!m_Reactor-&gt;reactor_event_loop_done ())</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>         <span style="color: #008000">// dont be too smart to move this outside the loop</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>         <span style="color: #008000">// the run_reactor_event_loop will modify interval</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>         ACE_Time_Value interval (0, 10000);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>         <span style="color: #008000">//（2）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>         <span style="color: #0000ff">if</span> (m_Reactor-&gt;run_reactor_event_loop (interval) == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>             <span style="color: #0000ff">break</span>;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>         <span style="color: #008000">//（3）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>         AddNewSockets ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span>         <span style="color: #0000ff">for</span> (i = m_Sockets.begin (); i != m_Sockets.end ();)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum21">  21:</span>         {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum22">  22:</span>             <span style="color: #008000">//（4）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum23">  23:</span>             <span style="color: #0000ff">if</span> ((*i)-&gt;Update () == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum24">  24:</span>             {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum25">  25:</span>                 t = i;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum26">  26:</span>                 ++i;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum27">  27:</span>                 (*t)-&gt;CloseSocket ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum28">  28:</span>                 (*t)-&gt;RemoveReference ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum29">  29:</span>                 --m_Connections;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum30">  30:</span>                 m_Sockets.erase (t);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum31">  31:</span>             }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum32">  32:</span>             <span style="color: #0000ff">else</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum33">  33:</span>                 ++i;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum34">  34:</span>         }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum35">  35:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum36">  36:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum37">  37:</span>     WorldDatabase.ThreadEnd ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum38">  38:</span>     DEBUG_LOG (<span style="color: #006080">"Network Thread Exitting"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum39">  39:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum40">  40:</span>     <span style="color: #0000ff">return</span> 0;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum41">  41:</span> }</pre><!--CRLF--></div></div>
<p>（1）会调用mysql_thread_init ()函数，初始化与该线程相关的变量。</p>
<p>（2）run_reactor_event_loop ()函数为多路复用的等待函数，当注册的事件发生、运行超时或者出现错误时返回。</p>
<p>（3）AddNewSockets ()函数会将缓存在m_NewSockets里的新到达的socket添加到SocketSet m_Sockets;里，同时检查并处理m_Sockets;里已经closed的socket。</p>
<p>（4）循环每一个WorldSocket，调用其Update ()方法，这里只处理每个socket的handle_output，即每个在此线程上的写事件，向客户端发送数据。下一节详细介绍：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><strong><font size="3">三、WorldSocket::Update () 方法</font></strong></span></p>
<p>Update方法用于处理每个socket的输出：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocket::Update (<span style="color: #0000ff">void</span>)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (closing_)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">//（1）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #0000ff">if</span> (m_OutActive || m_OutBuffer-&gt;length () == 0)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>         <span style="color: #0000ff">return</span> 0;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     <span style="color: #0000ff">return</span> handle_output (get_handle ());</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span> }</pre><!--CRLF--></div></div>
<p>（1）m_OutBuffer有数据时才会调用handle_output，handle_output ()用于处理输出，如果输出不能一次性做完，会调用schedule_wakeup_output ()再次激活write事件。当输出处理完毕后则调用cancel_wakeup_output ()取消激活write事件，使reactor恢复到正常的loop ()循环中。详细过程如下：</p>
<p>&nbsp;</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocket::handle_output (ACE_HANDLE)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #008000">//（1）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #0000ff">if</span> (closing_)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     <span style="color: #0000ff">const</span> size_t send_len = m_OutBuffer-&gt;length ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     <span style="color: #0000ff">if</span> (send_len == 0)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>         <span style="color: #0000ff">return</span> cancel_wakeup_output (Guard);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span> <span style="color: #cc6633">#ifdef</span> MSG_NOSIGNAL</pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>     ssize_t n = peer ().send (m_OutBuffer-&gt;rd_ptr (), send_len, MSG_NOSIGNAL);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span> <span style="color: #cc6633">#else</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>     ssize_t n = peer ().send (m_OutBuffer-&gt;rd_ptr (), send_len);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span> <span style="color: #cc6633">#endif</span> <span style="color: #008000">// MSG_NOSIGNAL</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>     <span style="color: #0000ff">if</span> (n == 0)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum21">  21:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (n == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum22">  22:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum23">  23:</span>         <span style="color: #0000ff">if</span> (errno == EWOULDBLOCK || errno == EAGAIN) <span style="color: #008000">//----------（2）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum24">  24:</span>             <span style="color: #0000ff">return</span> schedule_wakeup_output (Guard);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum25">  25:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum26">  26:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum27">  27:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (n &lt; (ssize_t)send_len) <span style="color: #008000">//now n &gt; 0      //----------（3）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum29">  29:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum30">  30:</span>         m_OutBuffer-&gt;rd_ptr (<span style="color: #0000ff">static_cast</span>&lt;size_t&gt; (n));</pre><!--CRLF--><pre><span style="color: #606060" id="lnum31">  31:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum32">  32:</span>         <span style="color: #008000">// move the data to the base of the buffer</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum33">  33:</span>         m_OutBuffer-&gt;crunch ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum34">  34:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum35">  35:</span>         <span style="color: #0000ff">return</span> schedule_wakeup_output (Guard);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum36">  36:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum37">  37:</span>     <span style="color: #0000ff">else</span> <span style="color: #008000">//now n == send_len                         //----------（4）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum38">  38:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum39">  39:</span>         m_OutBuffer-&gt;reset ();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum40">  40:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum41">  41:</span>         <span style="color: #0000ff">if</span> (!iFlushPacketQueue ())</pre><!--CRLF--><pre><span style="color: #606060" id="lnum42">  42:</span>             <span style="color: #0000ff">return</span> cancel_wakeup_output (Guard);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum43">  43:</span>         <span style="color: #0000ff">else</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum44">  44:</span>             <span style="color: #0000ff">return</span> schedule_wakeup_output (Guard);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum45">  45:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum46">  46:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum47">  47:</span>     ACE_NOTREACHED (<span style="color: #0000ff">return</span> 0);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum48">  48:</span> }</pre><!--CRLF--></div></div>
<p>（1）对m_OutBuffer加锁。</p>
<p>（2）考虑信号打断的情况等，暂时不能写。</p>
<p>（3）只发送了部分数据则继续wakeup该线程对应的Reactor。</p>
<p>（4）检查m_OutBuffer数据发送完毕同时等待buffer（PacketQueueT m_PacketQueue;）里已经没有数据时，cancel wakeup让Reactor恢复正常。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><font size="3">四、socket到对应线程的指派</font></span></p>
<p>上一节内容可以看到线程内如何处理socket，及新到达的socket。但从第一节中可知只有第一个线程注册为acceptor线程，那么新连接到达时，是如何被指派到对应的&#8220;接待&#8221;线程的呢？</p>
<p>可以先看一下ACE_Acceptor的处理时序图：<br /></p>
<p>&nbsp;</p>
<p style="text-align: center"><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/ming81/2011122421294328.jpg" /><br />图3.1 连接到达处理时序 [2]</p>
<p>&nbsp;</p>
<p>上图可以看出，当连接到达时，acceptor会调用对应的SVC_HANDLER的open ()函数，在mangosd里就是acceptor对应的int WorldSocket::open (void *a)，如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocket::open (<span style="color: #0000ff">void</span> *a)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #008000">// Hook for the manager.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #0000ff">if</span> (sWorldSocketMgr-&gt;OnSocketOpen (<span style="color: #0000ff">this</span>) == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span> }</pre><!--CRLF--></div></div>
<p>&nbsp;</p>
<p>OnSocketOpen方法：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocketMgr::OnSocketOpen (WorldSocket* sock)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #008000">// we skip the Acceptor Thread</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     size_t min = 1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     MANGOS_ASSERT (m_NetThreadsCount &gt;= 1);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     <span style="color: #008000">//（1）</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #0000ff">for</span> (size_t i = 1; i &lt; m_NetThreadsCount; ++i)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>         <span style="color: #0000ff">if</span> (m_NetThreads[i].Connections () &lt; m_NetThreads[min].Connections ())</pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>             min = i;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>     <span style="color: #0000ff">return</span> m_NetThreads[min].AddSocket (sock);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span> }</pre><!--CRLF--></div></div>
<p>（1）将WorldSocket均衡的分配给每个线程。AddSocket ()将socket添加到m_NewSockets中做缓存，待该线程自行调用AddNewSockets ()添加到处理队列里。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><strong><font size="3">总结：</font></strong></span></p>
<p>mangosd对socket的处理因为使用了ACE，逻辑处理代码相对比较简单，写事件的异常处理主要涉及</p>
<p>（1）一次不能写完则不断的wakeup Reactor。</p>
<p>（2）信号中断等错误的判断。似乎这里并没有考虑全面（见附录）</p>
<p>（3）使用另一个buffer缓存，因写缓存m_OutBuffer满而带来的多出的数据。</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><strong><font size="3">References：</font></strong></span></p>
<p>[1] <a title="http://blog.csdn.net/yecao_kinux/article/details/1546914" href="http://blog.csdn.net/yecao_kinux/article/details/1546914"><font color="#6466b3">http://blog.csdn.net/yecao_kinux/article/details/1546914</font></a></p>
<p>[2] <a title="http://postfiles12.naver.net/data41/2009/4/11/187/33_kbkim007.jpg?type=w3" href="http://postfiles12.naver.net/data41/2009/4/11/187/33_kbkim007.jpg?type=w3"><font color="#6466b3">http://postfiles12.naver.net/data41/2009/4/11/187/33_kbkim007.jpg?type=w3</font></a></p><img src ="http://www.cppblog.com/ming81/aggbug/185024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-25 14:49 <a href="http://www.cppblog.com/ming81/archive/2012/07/25/185024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)MaNGOS-Zero源码学习之mangosd游戏逻辑服务器（一）：登录认证及建立连接 </title><link>http://www.cppblog.com/ming81/archive/2012/07/25/185023.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 25 Jul 2012 06:37:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/25/185023.html</guid><description><![CDATA[mangosd是MaNGOS-Zero项目中的游戏逻辑进程，玩家一旦与realmd的keyexchange过程完成后（详细内容见《<a href="http://www.cppblog.com/ming81/archive/2012/07/24/184838.html"><font color="#6466b3">realmd认证登录服务器（一）：认证登录基本流程</font></a>》），便只与mangosd进行交互。而客户端与realmd的连接也会在客户端向mangosd发送enterworld之后断开。 
<p>本文将介绍客户端连接到mangosd后，mangosd认证客户端合法性并最终建立RC4流加密的过程。具体过程如下：</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/ychellboy/201111/201111261948219188.png"></a><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/ming81/201111261948222088.png" />&nbsp;</p>
<p>（1） 客户端与mangosd建立TCP连接后，mangosd会向客户端发送消息SMSG_AUTH_CHALLENGE</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">int</span> WorldSocket::open (<span style="color: #0000ff">void</span> *a)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #008000">// Send startup packet.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     WorldPacket packet (SMSG_AUTH_CHALLENGE, 4);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     packet &lt;&lt; m_Seed;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #0000ff">if</span> (SendPacket (packet) == -1)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>         <span style="color: #0000ff">return</span> -1;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span> }</pre><!--CRLF--></div></div>
<p>m_Seed是一个随机数，每次客户端连接上来的时生成一个新的随机数（随着WorldSocket的创建而初始化）。</p>
<p>&nbsp;</p>
<p>（2）客户端收到SMSG_AUTH_CHALLENGE消息后，知道服务器要求其提供身份认证信息，于是开始构造CMSG_AUTH_SESSION消息。（以下代码并非客户端真实代码）</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #008000">//client do auth</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     BigNumber clientSeed;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     clientSeed.SetRand(4 * 8);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     sha.Initialize();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     sha.UpdateData(<span style="color: #006080">"abu"</span>);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     uint32 t = 0;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     sha.UpdateData((uint8 *)&amp;t, 4);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     sha.UpdateBigNumbers(&amp;clientSend, NULL);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     sha.UpdateData((uint8 *)&amp;serverSeed, 4);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     sha.UpdateBigNumbers(&amp;K, NULL);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>     sha.Finalize();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>     uint32 unk2;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>     ByteBuffer pktbuf;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>     string account = <span style="color: #006080">"abu"</span>;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>     uint16 pktbuf_size = 4+4+4+account.length()+4+20;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>     EndianConvertReverse(pktbuf_size);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>     pktbuf &lt;&lt; uint16(pktbuf_size);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span>     pktbuf &lt;&lt; uint32(CMSG_AUTH_SESSION);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum21">  21:</span>     pktbuf &lt;&lt; uint32(5875); <span style="color: #008000">//build version</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum22">  22:</span>     pktbuf &lt;&lt; unk2;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum23">  23:</span>     pktbuf &lt;&lt; account;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum24">  24:</span>     pktbuf.append(clientSeed.AsByteArray(4), 4);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum25">  25:</span>     pktbuf.append(sha.GetDigest(), 20);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum26">  26:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum27">  27:</span>     send((<span style="color: #0000ff">char</span> <span style="color: #0000ff">const</span>*)pktbuf.contents(), pktbuf.size());</pre><!--CRLF--><pre><span style="color: #606060" id="lnum28">  28:</span> }</pre><!--CRLF--></div></div>
<p>其中最为关键的是构造20位的sha验证密文M：</p>
<blockquote>
<p>M = sha(t, account, clientSeed, serverSeed, K);</p>
<p>t为0；account是明文的用户名；clientSeed是由客户端生成的随机数，用于本次连接游戏session；serverSeed是SMSG_AUTH_CHALLENGE消息发过来的服务器随机数；K是之前和realmd交互做keyexchange时生成的，由服务器和客户端分别进行计算，SRP6算法要求(保证)两边的计算结果一致，服务器端保存在realmd.account.sessionkey字段。</p></blockquote>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>（3）服务器收到客户端发来的CMSG_AUTH_SESSION，首先对收到的数据包进行分析，客户端发来的数据包的包头如下：</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">struct</span> ClientPktHeader</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     uint16 size; <span style="color: #008000">//packet_size except itself</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     uint32 cmd;  <span style="color: #008000">//opCode</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span> };</pre><!--CRLF--></div></div>
<p>收到客户端发来的data，处理流程可以简化为如下代码：</p>
<p>int WorldSocket::handle_input (ACE_HANDLE)</p>
<p>{</p>
<p>&#8230;&#8230;&#8230;&#8230;&#8230;</p>
<p>handle_input_missing_data()</p>
<p>{</p>
<p>handle_input_header();</p>
<p>handle_input_payload()</p>
<p>{</p>
<p>const int ret = ProcessIncoming (m_RecvWPct);</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>在ProcessIncoming()函数中使用switch case把客户端发过来的不同的opcode定位到不同的处理函数中，而登录认证过程需要定位到int WorldSocket::HandleAuthSession (WorldPacket&amp; recvPacket)函数。</p>
<p>在HandleAuthSession()函数中，服务器以客户端相同的方式计算sha密文，并和客户端传来的做比较，如果相同则认证通过，然后创建WorldSession实例，初始化m_Crypt成员，以便以后服务器和客户端之间交互的RC4对称加密使用。最后把新创建的WorldSession对象的m_Session添加到游戏世界中，添加完毕后，在游戏世界的主线程(Update线程)可以对该客户端做相应的处理。</p>
<p>&nbsp;</p>
<p>（4）HandleAuthSession()处理的最后会使用下面的代码，进行判断：如果session可以作为normal_session的而不是queue_session则发送SMSG_AUTH_RESPONSE消息，至此所有发送的消息都将进行RC4的流加密。</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">void</span> World::AddSession_ (WorldSession* s)</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #0000ff">if</span> (pLimit &gt; 0 &amp;&amp; Sessions &gt;= pLimit &amp;&amp; s-&gt;GetSecurity () == SEC_PLAYER )</pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>         AddQueuedSession(s);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>         UpdateMaxSessionCounters();</pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>         DETAIL_LOG(<span style="color: #006080">"PlayerQueue: Account id %u is in Queue Position (%u)."</span>, s-&gt;GetAccountId (), ++QueueSize);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>         <span style="color: #0000ff">return</span>;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     }</pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #008000">// Checked for 1.12.2</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>     WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>     packet &lt;&lt; uint8 (AUTH_OK);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>     packet &lt;&lt; uint32 (0);                                   <span style="color: #008000">// BillingTimeRemaining</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>     packet &lt;&lt; uint8 (0);                                    <span style="color: #008000">// BillingPlanFlags</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span>     packet &lt;&lt; uint32 (0);                                   <span style="color: #008000">// BillingTimeRested</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum19">  19:</span>     s-&gt;SendPacket (&amp;packet);</pre><!--CRLF--><pre><span style="color: #606060" id="lnum20">  20:</span>  </pre><!--CRLF--><pre><span style="color: #606060" id="lnum21">  21:</span>     ........</pre><!--CRLF--><pre><span style="color: #606060" id="lnum22">  22:</span> }</pre><!--CRLF--></div></div>
<p>&nbsp;</p>
<p><strong>总结：</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>（1）realmd和mangosd在登录认证过程中，相互之间基本不通信，通过MySQL来传递client认证所需的sessionkey。</p>
<p>（2）每次客户端和mangosd之间认证时，各自生成一个随机数Seed，保证在传输过程中隐藏sessionkey。</p><img src ="http://www.cppblog.com/ming81/aggbug/185023.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-25 14:37 <a href="http://www.cppblog.com/ming81/archive/2012/07/25/185023.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)MaNGOS-Zero源码学习之realmd认证登录服务器（一）：认证登录基本流程 </title><link>http://www.cppblog.com/ming81/archive/2012/07/24/184838.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 24 Jul 2012 02:39:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/24/184838.html</guid><description><![CDATA[在MaNGOS-Zero中认证登录服务器是已独立的进程存在的，名字叫realmd，这样命名可能是和游戏client端根目录下的realmlist.wtf文件相对应。realmd的主要工作是：检查登录用户的合法性，并在合法的情况下完成通信密钥的交换，最后把游戏逻辑服务器的地址信息列表传给client端。 
<p>realmd认证的基本流程如下：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/ming81/201110302035407215.png" /></p>
<p><a href="http://images.cnblogs.com/cnblogs_com/ychellboy/201110/201110302035369629.png"></a></p>
<p>图中的（1）~（7）详细过程如下：</p>
<p>（1）Client启动后立即尝试连接realmlist.wtf文件中指定的认证服务器，就发送LogonChallenge给认证服务器realmd。协议结构如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">typedef</span> <span style="color: #0000ff">struct</span> AUTH_LOGON_CHALLENGE_C</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     uint8   cmd;                <span style="color: #008000">//Cmd is the command/operation code of the packet. Always 0 for this message</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     uint8   error;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     uint16  size;            <span style="color: #008000">//Size of the remaining part of the message</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     uint8   gamename[4];    <span style="color: #008000">//4 byte C-String, containing the String "WoW\0"</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     uint8   version1;            <span style="color: #008000">//Major version number of the client ( 1 for 1.12.1 )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     uint8   version2;            <span style="color: #008000">//Minor version number of the client ( 12 for 1.12.1 )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     uint8   version3;            <span style="color: #008000">//Patchlevel version number of the client ( 1 for 1.12.1 )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     uint16  build;            <span style="color: #008000">//Build number of the client. ( 5875 for 1.12.1 )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     uint8   platform[4];        <span style="color: #008000">//Platform the client is running on, reversed C-String ( "68x\0" for x86 )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>     uint8   os[4];            <span style="color: #008000">//OS the client is running on, reversed C-String ( "niW\0" for Windows )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>     uint8   country[4];        <span style="color: #008000">//Locale of the client, reversed C-String ( "SUne" for enUS )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span>     uint32  timezone_bias;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum15">  15:</span>     uint32  ip;                <span style="color: #008000">//IP address of the client in binary format</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum16">  16:</span>     uint8   I_len;            <span style="color: #008000">//Length of the Identity ( user name ) in characters</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum17">  17:</span>     uint8   I[1];                <span style="color: #008000">//The Identity string ( user name )</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum18">  18:</span> } sAuthLogonChallenge_C;</pre><!--CRLF--></div></div>
<p>uint8 I[1]是一个unsigned char的变长数组的头指针，保存user name，服务器端保存的时候要把\0后面的东西去掉，防止SQL injection。（1.1）执行&#8220;SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '%s'&#8221;语句从数据库中读取数据。</p>
<blockquote>
<p>realmd收到sAuthLogonChallenge_C协议后处理步骤如下：</p></blockquote>
<blockquote>
<p>1) 检查该ip是否被封禁，如果是发送相应的错误</p>
<p>2) 查询数据库中是否有该账户，如果没有返回相应的错误</p>
<p>3) 查看最后一次登录ip与账户是否绑定，如果绑定对比当前ip与last_ip是否一致</p>
<p>4) 检查该账号是否被封禁，如果是发送相应的错误信息</p>
<p>5) 获取用户名密码，开始SRP6计算，参见本文最下方的附录《MaNGOS所使用的SRP6算法》</p>
<p>6) _accountSecurityLevel，保存用户的权限等级，普通用户、GM、admin等等</p>
<p>7) 本地化：根据_localizationName的名字找对应的.mpq文件所在的位置比如enUS，zhTW，zhCN</p></blockquote>
<p>&nbsp;</p>
<p>（2） realmd向client发送challenge，协议如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">typedef</span> <span style="color: #0000ff">struct</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     uint8   cmd;            <span style="color: #008000">//Cmd is the command/operation code of the packet. Always 0 for this message.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     uint8   error;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     uint8   unk2;        <span style="color: #008000">//random value</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     uint8   B[32];        <span style="color: #008000">//B is an SRP6 value. It is the server's public value.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     uint8   g_len;        <span style="color: #008000">//Length of the SRP6 g value we send the client in bytes. Always 1</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     uint8   g[1];            <span style="color: #008000">//The SRP6 g value we send the client. Always 7</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span>     uint8   N_len;        <span style="color: #008000">//Lenght of the SRP6 N value we send the client. Always 32</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum10">  10:</span>     uint8   N[32];        <span style="color: #008000">//The SRP6 N value we send the client. </span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum11">  11:</span>     uint8   s[32];        <span style="color: #008000">//The SRP6 s value</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum12">  12:</span>     uint8   unk3[16];        <span style="color: #008000">//a randomly generated 16 byte value.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum13">  13:</span>     uint8   unk4;        <span style="color: #008000">//a single byte 0.</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum14">  14:</span> } sAuthLogonChallenge_S;</pre><!--CRLF--></div></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>（3）客户端的Handshaking阶段，client为了回应realmd的challenge消息，证明client的密码和server上保存的密码一致，需要计算M1值，并发送给realmd，发送的协议如下：</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">typedef</span> <span style="color: #0000ff">struct</span> AUTH_LOGON_PROOF_C</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     uint8   cmd;                    <span style="color: #008000">//Cmd is the command/operation code of the packet. Always 1 for this message</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     uint8   A[32];                <span style="color: #008000">//The client SRP6 A value ( public client value ).</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     uint8   M1[20];                <span style="color: #008000">//The client's SRP6 M value.待比较的最终值</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     uint8   crc_hash[20];            <span style="color: #008000">//doesn't seem to be used</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     uint8   number_of_keys;        <span style="color: #008000">//It also seems to be always 0</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     uint8   securityFlags;                 <span style="color: #008000">// 0x00-0x04</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span> } sAuthLogonProof_C;</pre><!--CRLF--></div></div>
<p>计算公式如下，各个变量的含义请查看本文最下方的附录《MaNGOS所使用的SRP6算法》</p>
<p>A = g^a mod N //a为19个字节的随机数</p>
<p>B = (kv + g^b) mod N</p>
<p>u = H(A, B)</p>
<p>x = H(s, p)</p>
<p>S = (B - kg^x) ^ (a + ux)</p>
<p>K = H(S)</p>
<p>M = H(H(N) xor H(g), H(I), s, A, B, K)</p>
<p>上诉的哈希函数H都使用的是SHA1</p>
<p>&nbsp;</p>
<p>（4）realmd收到client发来的Proof协议，(a)开始检查版本是否允许，(b) 使用SRP6计算M值，与client传过来的M1做对比，if (!memcmp(M.AsByteArray(), lp.M1, 20)) { } (c) 如果M值相等计算K &#8212;&#8212; 即sessionkey，并最终保存到数据库。</p>
<p>&nbsp;</p>
<p>（5）验证成功，realmd向client发送server的logon proof</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><pre><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">typedef</span> <span style="color: #0000ff">struct</span> AUTH_LOGON_PROOF_S</pre><!--CRLF--><pre><span style="color: #606060" id="lnum2">   2:</span> {</pre><!--CRLF--><pre><span style="color: #606060" id="lnum3">   3:</span>     uint8   cmd;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum4">   4:</span>     uint8   error;</pre><!--CRLF--><pre><span style="color: #606060" id="lnum5">   5:</span>     uint8   M2[20];            <span style="color: #008000">//The SRP6 M values，M = H(H(N) xor H(g), H(I), s, A, B, K)</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum6">   6:</span>     uint32  unk1;            <span style="color: #008000">// AccountFlags (trial 0x08, ProPass 0x800000, gm 0x01)</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum7">   7:</span>     uint32  unk2;            <span style="color: #008000">// SurveyId</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum8">   8:</span>     uint16  unk3;            <span style="color: #008000">// some flags (AccountMsgAvailable = 0x01)</span></pre><!--CRLF--><pre><span style="color: #606060" id="lnum9">   9:</span> } sAuthLogonProof_S;</pre><!--CRLF--></div></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>（6）_HandleRealmList，查询realmcharacters表获得角色和realmid的对应关系，然后可以在RealmList类里通过realmid找到对应的表项，RealmList在初始化的时候再realmlist表里读取数据放在内存里使用：&#8220;SELECT id, name, address, port, icon, realmflags, timezone, allowedSecurityLevel, population, realmbuilds FROM realmlist WHERE (realmflags &amp; 1) = 0 ORDER BY name &#8221; 查询逻辑服务器。</p>
<p>&nbsp;</p>
<p>（7）发送realmlist给客户端，客户端选择对应的服务器后点击enter world的时，会主动断开和realmd的连接。</p>
<p>&nbsp;</p>
<p><strong>总结：</strong>整个登录认证过程主要干了如下几件事</p>
<p>(a)使用公钥算法验证client的合法性。</p>
<p>(b)client合法的情况下，计算sessionkey并保存在MySQL里，以备后面的逻辑服务器使用。</p>
<p>(c)验证通过后，把逻辑服务器列表发给client。</p>
<p>其中最为重要的就是在验证合法性、交换密钥的过程中，如何在传递的协议里隐藏client的密钥，使其在被截获的情况下也无法被黑客解析，这就只能依仗密码学了。WOW所使用的加密算法是SRP6，详细的介绍如下：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>附录：MaNGOS所使用的SRP6算法</strong></p>
<blockquote>
<p>SRP全称Secure Remote Password(安全远程密码).使用SRP的客户机和服务器不会在网络上传送明文密码，这样可以消除直接密码嗅探行为，另外使用高强度的算法保证了不可能使用字典法攻击嗅探到的数据[1]。SRP协议的描述见 <a href="http://srp.stanford.edu/design.html"><font color="#6466b3">http://srp.stanford.edu/design.html</font></a></p></blockquote>
<p><strong>SRP6</strong><strong>名词解释：</strong></p>
<blockquote>
<p>N - A large safe prime (N = 2q+1, where q is prime) All arithmetic is done modulo N.</p>
<p>g - A generator modulo N</p>
<p>k - Multiplier parameter (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6)</p>
<p>s - User's salt</p>
<p>I - Username</p>
<p>p - Cleartext Password</p>
<p>H() - One-way hash function</p>
<p>^ - (Modular) Exponentiation</p>
<p>u - Random scrambling parameter</p>
<p>a,b - Secret ephemeral values</p>
<p>A,B - Public ephemeral values</p>
<p>x - Private key (derived from p and s)</p>
<p>v - Password verifier</p></blockquote>
<p><strong>对应MaNGOS的计算方法和变量含义：</strong></p>
<blockquote>
<p>sha_pass_hash：使用这个函数进行Sha1Hash哈希std::string AccountMgr::CalculateShaPassHash(std::string&amp; name, std::string&amp; password)后得到的值。</p>
<p>N： A large safe prime (N = 2q+1, where q is prime)， All arithmetic is done modulo N. 在MaNGOS里N被设成N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");</p>
<p>s： 32个字节的随机数，算过一次后保存在数据库里。</p>
<p>x： 计算v值使用到的x，即私钥是s与数据库里的sha_pass_hash的倒置的Sha1Hash</p>
<p>v： g^x mod N，验证密码时使用Password verifier，算过一次后保存在数据库里。</p>
<p>g： g = 7</p>
<p>b： 为19个字节的随机数，每次client连接认证的时候重新生成。</p>
<p>a： 19个字节的随机数，由客户端产生。</p>
<p>B： 公钥， gmod = g^b, N , B = ((v * 3) + gmod) % N</p>
<p>K： 认证通过后最终保存到数据库里的sessionkey，(1)计算A 客户端公钥A = g^a mod N a为19为随机数，（2）计算x，x = sha(s, I)，I = sha(&#8220;username : password&#8221;)； （3）计算u，u = sha(A, B) //（服务公钥，客户公钥）；（4）计算S，S = (B - g^x*3)^(a+u*x)； （5）计算K，S为32位，K为40位是 sha(s奇部分）20位, sha(s偶部分）20位的奇偶交错组合。</p>
<p>M： 20个字节的数，用于与client传过来的最终结果M1进行对比，如果M和M1每个字节都相等则验证通过。计算方法：t3 = sha(N)[i] ^ sha(g)[i]，t4 = sha(username)，M = sha(t3,t4,s,A,B,K)</p>
<p>k： k = 3</p></blockquote>
<p><strong>总结：</strong>服务端,客户端各自计算S的公式个不同，公钥部分服务端用A,b, 客户端用B,a 但其计算结果相同&#8230;&#8230;&#8230;私钥x被很好的隐藏了，因为想从M获得x是基本不可能的！基于数学难题基础上的加密算法确实很给力。</p>
<p>&nbsp;</p>
<p><strong>References</strong>：</p>
<p>[1]<a href="http://blog.csdn.net/lfhfut/article/details/1124768"><font color="#6466b3">http://blog.csdn.net/lfhfut/article/details/1124768</font></a></p>
<p>[2]<a href="http://www.arcemu.org/wiki/"><font color="#6466b3">http://www.arcemu.org/wiki/</font></a></p>
<p>[3]<a href="http://hi.baidu.com/zyy503950958/blog/item/3addce90a91eda81a877a463.html"><font color="#6466b3">http://hi.baidu.com/zyy503950958/blog/item/3addce90a91eda81a877a463.html</font></a></p><img src ="http://www.cppblog.com/ming81/aggbug/184838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-24 10:39 <a href="http://www.cppblog.com/ming81/archive/2012/07/24/184838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)MaNGOS-Zero编译注意事项 </title><link>http://www.cppblog.com/ming81/archive/2012/07/24/184836.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 24 Jul 2012 02:35:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/24/184836.html</guid><description><![CDATA[最近周末咸蛋，抽时间看了一下传说中的开源WOW服务器模拟器，虽然只看了登陆认证这块，但感触颇多，兴起随便写写。 
<p>MaNGOS的介绍如下：</p>
<blockquote>
<h4>What is MaNGOS?</h4>
<p>The <em>mangos project</em> is a full featured <a href="http://worldofwarcraft.com/"><font color="#6466b3">World of Warcraft</font></a> server suite, including servers for authentication, client updates, world content serving, and battlegrounds. Additional features include tools to build and develop game content. It is compatible with <a href="http://www.worldofwarcraft.com/info/underdev/implemented/3p3.xml"><font color="#6466b3">client version 3.3.5a</font></a>.</p>
<p><em>mangos</em> is an educational project. This means, our primary interest is to learn and teach us and our users more about <a href="http://cppreference.com/"><font color="#6466b3">C++</font></a> project development in a large scale. Our software is not intended for running public servers, and we do not support that.</p></blockquote>
<p>本篇所编译的mangos版本是MaNGOS-Zero，对应的客户端版本是1.12.1 (build 5875) ~ 1.12.2 (build 6005)。这是现在所能找到的最原始的版本，之所以选择这个版式，因为想看看mangos&#8220;化妆前&#8221;的摸样，从较早的版本开始看也是我的习惯。</p>
<p>主要的编译过程和方法参照：<a href="http://hi.baidu.com/sunsee/blog/item/8b34f043238dd51972f05d15.html"><font color="#6466b3">http://hi.baidu.com/sunsee/blog/item/8b34f043238dd51972f05d15.html</font></a></p>
<p>client 1.12.1(build 5875)的下载地址是：<a href="http://thepiratebay.org/torrent/5158084/World_of_Warcraft_1.12.1_Full_Client___Patches"><font color="#6466b3">http://thepiratebay.org/torrent/5158084/World_of_Warcraft_1.12.1_Full_Client___Patches</font></a></p>
<p><font color="#6466b3"></font></p>
<p>这里主要进行以下补充和一些注意事项的说明：</p>
<ol><li><em><strong>获取代码：</strong></em>使用git从下面给出的mangos、scripts和database三个连接里去获取对应的代码，<strong>没有注册登录就直接用http下载可能不是最新的版本，导致程序版本和db版本对不上</strong>。&#8220;Looking for <em>client 1.12.1</em> support? No need to hold your breath, there is a solution for you. <em>mangos zero</em>, an offspring project of <em>mangos</em> has your back covered. The <a href="https://github.com/mangos-zero/server"><font color="#6466b3">server</font></a>, the <a href="https://github.com/mangos-zero/scriptdev0"><font color="#6466b3">scripts</font></a>, and the <a href="https://github.com/mangos-zero/database"><font color="#6466b3">database</font></a> are available. <em>mangos zero</em> has its' own <a href="http://zeroproject.udworld.net/forum.php"><font color="#6466b3">forums</font></a>, too&#8221;</li><li><strong><em>检查版本一致：</em></strong>下载完毕后对照/mangos-zero/src/shared/revision_sql.h文件里的三个宏：REVISION_DB_CHARACTERS、REVISION_DB_MANGOS、REVISION_DB_REALMD的值和所下载的database对应的表是否一致，分别对应：character/character_db_version、mangos/db_version、realmd/realmd_db_version</li><li><strong><em>DB版本：</em></strong>其实直接使用mangos-zero/sql目录下的sql文件也是可以的，不需要单独取database文件。</li><li><strong><em>所需配置文件：</em></strong>realmd.exe、mangos.exe运行所需要的配置文件分别是mangosd.conf、realmd.conf、mods.conf、scriptdevzero.conf在mangos目录下能找到以*.dist.in结尾的配置文件模板，拷贝并修改名字后即可使用。</li><li><strong><em>ScriptDev2：</em></strong>要放在src/binding目录下，VS2010可以顺利的编译通过。VS2005要编译Debug版没有问题，编译成Debug_NoPCH不能通过，不知道为什么？</li><li><strong><em>contrib：</em></strong>mangos/contrib目录下是各种小工具及源码，包括解压maps的ad.exe，解压vmaps的vmap_extractor。</li><li><strong><em>解压vmaps文件：</em></strong>将使用/contrib/vmap_extract_assembler_bin目录下的所有文件拷贝到客户端的根目录，运行makevmaps_SIMPLE.bat即可。如果系统中存在两个以上的WOW客户端，则需要按照以下步骤进行：(a)使用-d参数指定目录的位置，比如 vmapextractor3.exe -d Data 等待程序提取和分析map data；(b)然后再相同目录下直接运行vmap_assembler.exe生成vmaps </li></ol>
<p>&nbsp;</p>
<p>配置文件说明：</p>
<p>（1）mangos.conf</p>
<ul><li>看代码时经常会设置断点，为了不让连接断开可以将配置文件里的MaxOverspeedPings设置为0 </li></ul><img src ="http://www.cppblog.com/ming81/aggbug/184836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-24 10:35 <a href="http://www.cppblog.com/ming81/archive/2012/07/24/184836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)网游服务端技术总结 四</title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184743.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 07:50:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184743.html</guid><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">game server内嵌的http服务<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">如何使gs响应http的请求？ 基本思路 实现简单的http server框架、具体游戏逻辑转发给内部handler来处理<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一 初始化<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 开启监听线程（协程）检查端口、设置缓冲区大小<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 每一个socket连过来时 1、开新协程处理（有调度开销）&nbsp; 2、放入共享队列中，由worker线程池共同维护（有数据同步的问题）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 设置每个请求URI对应的回调接口<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">二 服务期<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 1、一个socket数据到来后，开新线程，解析http数据，分析出请求的uri、回调、关闭socket、关闭线程（因为http是无连接的）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 2、一个socket到来时，其被放入某个thread内部的sockets数组中，<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 当此worker thread池被调度到之后，依次处理每个socket的数据就可以了（唯一区别是多个sockets由几个线程维护）</span><img src ="http://www.cppblog.com/ming81/aggbug/184743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 15:50 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)网游服务端技术总结 三</title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184719.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 05:50:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184719.html</guid><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp; session管理<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一、world核心数据结构：环境+session<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">SessionMap m_sessions;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Queue m_QueuedSessions;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">typedef UNORDERED_MAP&lt;uint32, Weather*&gt; WeatherMap;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WeatherMap m_weathers;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">二、WorldSession 核心数据结构 玩家+信道+消息队列<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; Player *_player;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; WorldSocket *m_Socket;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; ACE_Based::LockedQueue&lt;WorldPacket*, ACE_Thread_Mutex&gt; _recvQueue; // 每个session有一个消息队列<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">整个session就是不停的fetch，处理msg的过程<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; OpcodeHandler const&amp; opHandle = opcodeTable[packet-&gt;GetOpcode()];&nbsp; // 利用一次映射找到handler<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">handle_input_payload----int WorldSocket::ProcessIncoming (WorldPacket* new_pct)--------void WorldSession::QueuePacket(WorldPacket* new_packet)<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">三、player核心数据结构 map、权限、社会关系、管理员？拍卖？谈话 存储 包裹 物品&#8230;&#8230;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">概述：所有command缓存在socket的队列中，各个子系统的总入口是player<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">服务端每一帧的逻辑：<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1、从OS处取出到达的事件到本进程（所有的事件已经缓存在socket队列中）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2、依次调度各个子系统或子子系统<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">对于node.js而言，线程调度、事件缓存、回调机制已经都实现了，程序员只要实现具体的逻辑和定时器（子系统）就可以了<span class="Apple-converted-space">&nbsp;</span></span><img src ="http://www.cppblog.com/ming81/aggbug/184719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 13:50 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)网游服务端技术总结 二</title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184717.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 05:48:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184717.html</guid><description><![CDATA[<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; font: 14px/1.8em Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="blog_content" class="blog_content">GS生命期内主要的事件---------状态机的状态转换主要是基于事件<span class="Apple-converted-space">&nbsp;</span><br /><br />一 game server状态机<span class="Apple-converted-space">&nbsp;</span><br />startup<span class="Apple-converted-space">&nbsp;</span><br />LOAD<span class="Apple-converted-space">&nbsp;</span><br />Compile<span class="Apple-converted-space">&nbsp;</span><br />init<span class="Apple-converted-space">&nbsp;</span><br />running<span class="Apple-converted-space">&nbsp;</span><br />shutdown<span class="Apple-converted-space">&nbsp;</span><br /><br />二 角色状态机<span class="Apple-converted-space">&nbsp;</span><br />login<span class="Apple-converted-space">&nbsp;</span><br />enter_world<span class="Apple-converted-space">&nbsp;</span><br />enter_map<span class="Apple-converted-space">&nbsp;</span><br />leave_map<span class="Apple-converted-space">&nbsp;</span><br />leave_world<span class="Apple-converted-space">&nbsp;</span><br />relogin<span class="Apple-converted-space">&nbsp;</span><br />logout<span class="Apple-converted-space">&nbsp;</span><br /><br />三 角色commands的命令种类<span class="Apple-converted-space">&nbsp;</span><br />login、auction, buy, chat, express, move, task, select_menu_item, stall&#8230;&#8230;<span class="Apple-converted-space">&nbsp;</span><br /><br />四 server端service的组织<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 1、结构化（纯c实现） clone, feature、cmds(命令入口filter)、daemons（抽象的功能模块）<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 2、OO&nbsp; 各个层次的router，XXHandler， 一般在session中的总入口是player</div><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 13px/18px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></span>
<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; display: block; font: 13px/18px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="bottoms" class="clearfix"><br class="Apple-interchange-newline" /></div><img src ="http://www.cppblog.com/ming81/aggbug/184717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 13:48 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)网游服务端技术总结 基于mangos源码 （一）</title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184710.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 03:40:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184710.html</guid><description><![CDATA[<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">整个game server的并发模型<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一 概述<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">game server至少要提供如下几类的功能 ：<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 1、响应客户端请求-------WorldRunnable<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 2、后台命令&nbsp; -------CliRunnable<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 3、分布式架构（RMI等） -------MaNGOSsoapRunnable<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">可以看到针对这几类功能，mangos都给予了支持。<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">二、WorldRunnable响应客户端请求的并发实现<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; game server会提供很多服务，如组队、加好友、交易、走路、战斗&#8230;&#8230;，从宏观上讲这些服务是同时对外提供的，另外IO操作是费时的，<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">必须将IO与逻辑处理分开，这样的话一个基本的实现是这样的：<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1、开启IO线程，所有费时的操作交由此处处理&nbsp;&nbsp; WorldDatabase.ThreadStart();<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2、利用协程来实现各个子系统，或者利用心跳来实现各个子系统的调度（不能开很多线程，线程代价太高）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">三、Mangos的心跳实现<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">void World::Update(uint32 diff)<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 基本上包括几类:<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 1、检查定时器---------------时间<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 2、刷任务<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 3、维护session---------------------人物<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 4、全局环境更新（map、battleGround）--------地点<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 5、处理服务器事件------------------事件<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 6、其他（数据同步、后台调试、IO回调&#8230;&#8230;）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">四、game server运行的机制<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 1、定时器触发<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp; 2、事件触发（松耦合）<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">五、典型的一种service的实现方式<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1、IO协程将cammand入队<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2、worker协程 依次fetch、execute<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 核心数据结构是线程安全的队列<span class="Apple-converted-space">&nbsp;</span></span><img src ="http://www.cppblog.com/ming81/aggbug/184710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 11:40 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)mangos 的执行模型 </title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184708.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 03:34:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184708.html</guid><description><![CDATA[<p>一、线程分布： <br />1、主线程 main---- Master::Run() ，主要功能：初始化world、创建子线程、回收资源 <br />2、WorldRunnable -------GS主线程 <br />3、CliRunnable -----后台调试线程 <br />4、RARunnable -------事件处理和分发线程 <br />5、MaNGOSsoapRunnable---协议 <br />6、FreezeDetectorRunnable <br />7、线程池&nbsp; Master::Run----WorldSocketMgr::StartNetwork---WorldSocketMgr::StartReactiveIO ---ReactorRunnable </p>
<p>二、事件分发和处理 <br />WorldRunnable::run---World:update----World:UpdateSessions---WorldSession::Update(一个socket内所有事件)---各种各样的handler </p>
<p>基本框架：ACE的Reactor机制（ACE_TP_Reactor） </p>
<p>三、WorldRunnable 主要功能 <br />WorldRunnable ----World 定时器任务+网络事件（session中的）+异步IO回调+任务系统调度+cli </p><img src ="http://www.cppblog.com/ming81/aggbug/184708.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 11:34 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184708.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)关于mangos多线程处理方式</title><link>http://www.cppblog.com/ming81/archive/2012/07/23/184706.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Mon, 23 Jul 2012 03:25:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/23/184706.html</guid><description><![CDATA[<div id="cnblogs_post_body">由于目前的MANGOS只是针对个人单机用户制作的，并非真正的服务器版。使用的是单<u><font color="red">线程</font></u>的处理方式。<br />关于mangos多<u><font color="red">线程</font></u>处理方式<br /><br />听说配置这个文件是管理<u><font color="red">线程</font></u>的，不过不知道有没有用！<br /># 在多<u><font color="red">线程</font></u>系统 使用线程MASK(只在Windows系统下使用)<br /># 默认: 0 (操作系统来选择)<br /># 举例: 数字<br />UseProcessors = 0<br /><br />目前的mangos上了几十人后，只要有组队的组团的就会卡，奇怪CPU占用也不高。请教了大大之后明白原来是mangos自身的瓶颈问题。<br /><br />CK说：<br />由于目前的MANGOS只是针对个人单机用户制作的，并非真正的服务器版。使用的是单<u><font color="red">线程</font></u>的处理方式。这个由代码就可以看出，整个World（包括人物，怪等）都是靠World.cpp里的update函数发起掉用的。而他是使用单<u><font color="red">线程</font></u>的方式，从头遍历所有的玩家，一个一个按照次序的来进行获取封包，并处理然后发送。这也就是为什么，当你打开MANGOS这个服务端，竟然CPU占用很少的原因。<br />在网上，我也看到过有人打算用多开区（EXE）来达到玩家分流，也只是治表不治本的方法。按照MANGOS的框架总体上来说人数达到100其实是一个上限值再上去的话，可能情况就是PING值虽然不高，但还是觉得卡。因为玩家封包没有及时处理，而停留在&#8220;等待处理&#8221;中。卡怪，卡魔法这样的情况很容易产生。特别当有一个PING值非常高的玩家，在SESSION排队列表里比你靠前时，这种情况最容易发生。<br /><br />CK给出的代码：<br />在World.cpp文件里，做一个<u><font color="red">线程</font></u>函数来代替<br />update函数里的<br /><br />CODE:<br /><br />for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)<br />{<br />next = itr;<br />next++;<br /><br />if(!itr-&gt;second)<br />continue;<br /><br />if(!itr-&gt;second-&gt;Update(diff))<br />{<br />delete itr-&gt;second;<br />m_sessions.erase(itr);<br />}<br />}<br />[url=javascript:][Copy to clipboard][/url]<br /><br />以上代码就是我刚才说的，从头遍历所有玩家并依次调用，所有玩家session的update函数。以下是修正建立自己的<u><font color="red">线程</font></u><br />CODE:<br /><br />DWORD World::_UpdateThread(LPVOID lp)<br />{<br />ThreadParm *parm = (ThreadParm *)lp;<br />World *pworld = (World *)parm-&gt;world;<br />HANDLE m_hSingle = NULL;<br />while (true)<br />{<br />SessionMap sessions = pworld-&gt;GetSessions();<br />SessionMap::iterator itr = NULL;<br />SessionMap::iterator next = NULL;<br /><br />for (itr = sessions.begin(), next; itr != sessions.end(); itr = next)<br />{<br />next = itr;<br />next++;<br /><br />if(itr == NULL || !itr-&gt;second || itr-&gt;second-&gt;GetWorking())<br />continue;<br /><br />m_hSingle = OpenEvent(EVENT_ALL_ACCESS,true,"worldsession"); //这里必须对所操作资源进行同步处理，否则将会出现<u><font color="red">线程</font></u>之间资源访问的冲突。一个<u><font color="red">线程</font></u>处理一个玩家，其他<u><font color="red">线程</font></u>直接跳转到后面的列队<br />if (m_hSingle == NULL)<br />{<br />m_hSingle = CreateEvent(NULL, FALSE, TRUE, "worldsession");<br />}<br />if (WaitForSingleObject(m_hSingle, 10000) == WAIT_TIMEOUT)//我把超时设置为10秒，以防死锁<br />{<br />SetEvent(m_hSingle);<br />m_hSingle = CreateEvent(NULL, FALSE, TRUE, "worldsession");<br />}<br />itr-&gt;second-&gt;SetWorking(true);<br />SetEvent(m_hSingle); //记得别忘了把锁打开，否则这个玩家之后所有的封包操作将被忽略。<br />if (!itr-&gt;second-&gt;Update(time(NULL)))<br />{<br />pworld-&gt;RemoveErrorSession(itr-&gt;second-&gt;GetAccountId());<br />}<br />else<br />{<br />itr-&gt;second-&gt;SetWorking(false);<br />}<br />}<br />Sleep(100); //线程间隔时间我设置为0.1秒<br />} <br />return 0;<br />}<br />[url=javascript:][Copy to clipboard][/url]<br /><br />接下来就是如何去开启<u><font color="red">线程</font></u>进行处理了，在world.cpp里有个SetInitialWorldSettings函数，这个是初始化World里面所有数据的总入口。我们可以把<u><font color="red">线程</font></u>启动放那里。<br />先在mangosd.conf文件里设置一串<br />CODE:<br />WorldSessionThread = 3<br />[url=javascript:][Copy to clipboard][/url]<br />设置3个启动<u><font color="red">线程</font></u><br />接下去就是在SetInitialWorldSettings里修改了<br />CODE:<br /><br />....<br />sLog.outString( "Loading Loot Tables..." );<br />LoadLootTables();<br />//在这里添加我们的<u><font color="red">线程</font></u>函数<br />for (int i = 0; i diff = i;<br />t-&gt;world = this;<br />::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_UpdateThread,(LPVOID)t,0,&amp;tid);<br />}<br />[url=javascript:][Copy to clipboard][/url]<br />GetIntDefault函数第一个我就不解释了，第二个值是表示默认值，比如你配置文件里没设置WorldSessionThread = 3这条语句的话，默认就是2个<u><font color="red">线程</font></u>。<br /><br />这样一来，我们的MANGOS服务端在处理能力上，将得到很大的提升<br /><br /><br />龙苑的林碧给出的提示：<br />thread.cpp<br /><br />#include &lt;stdio.h&gt;<br />#ifdef _WIN32<br />#include "socket_include.h"<br />#else<br />#include &lt;unistd.h&gt;<br />#endif<br /><br />#include "Thread.h"<br /><br />#ifndef __GNUC__<br /><br />// UQ1: warning C4311: 'type cast' : pointer truncation<br />#pragma warning(disable:4311)<br /><br />#endif<br /><br />Thread::Thread(bool release)<br />:m_thread(0)<br />,m_running(true)<br />,m_release(false)<br />{<br />#ifdef _WIN32<br />m_thread = ::CreateThread(NULL, 0, StartThread, this, 0, &amp;m_dwThreadId);<br />#else<br />pthread_attr_t attr;<br /><br />pthread_attr_init(&amp;attr);<br />pthread_attr_setdetachstate(&amp;attr,PTHREAD_CREATE_DETACHED);<br />if (pthread_create(&amp;m_thread,&amp;attr,StartThread,this) == -1)<br />{<br />perror("Thread: create failed");<br />SetRunning(false);<br />}<br />// pthread_attr_destroy(&amp;attr);<br />#endif<br />m_release = release;<br />}<br /><br /><br />Thread::~Thread()<br />{<br />// while (m_running || m_thread)<br />if (m_running)<br />{<br />SetRunning(false);<br />SetRelease(true);<br /><br />#ifdef _WIN32<br />struct timeval tv;<br />tv.tv_sec = 0;<br />tv.tv_usec = 100000;<br />select(0,NULL,NULL,NULL,&amp;tv);<br />::CloseHandle(m_thread);<br />#else<br />sleep(1);<br />#endif<br />}<br />}<br /><br /><br />threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz)<br />{<br />Thread *pclThread = (Thread *)zz;<br /><br />while (pclThread -&gt; m_running &amp;&amp; !pclThread -&gt; m_release)<br />{<br />#ifdef _WIN32<br />struct timeval tv;<br />tv.tv_sec = 0;<br />tv.tv_usec = 100000;<br />select(0,NULL,NULL,NULL,&amp;tv);<br />#else<br />sleep(1);<br />#endif<br />}<br />if (pclThread -&gt; m_running)<br />{<br />pclThread -&gt; Run();<br />}<br />pclThread -&gt; SetRunning(false); // if return<br />return (threadfunc_t)zz;<br />}<br /><br /><br />bool Thread::IsRunning()<br />{<br />return m_running;<br />}<br /><br /><br />void Thread::SetRunning(bool x)<br />{<br />m_running = x;<br />}<br /><br /><br />bool Thread::IsReleased()<br />{<br />return m_release;<br />}<br /><br /><br />void Thread::SetRelease(bool x)<br />{<br />m_release = x;<br />} </div><img src ="http://www.cppblog.com/ming81/aggbug/184706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-23 11:25 <a href="http://www.cppblog.com/ming81/archive/2012/07/23/184706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(七)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184370.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:58:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184370.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 6.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;H2测试方案6.2.1&nbsp;&nbsp;&nbsp;测试环境&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主机：&nbsp;&nbsp;&nbsp;&nbsp;操作系统：&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.cppblog.com/ming81/archive/2012/07/20/184370.html'>阅读全文</a><img src ="http://www.cppblog.com/ming81/aggbug/184370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:58 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(八)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184371.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:58:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184371.html</guid><description><![CDATA[<h2><span style="font-size: large"><span>&nbsp;&nbsp;</span>结论和建议</span></h2>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small"><span>&nbsp;SQLite</span>和<span>H2</span>内存数据库都比较快。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">查询性能：查询一条记录<span>&nbsp;SQLite</span>的性能要优于<span>H2</span>。查询（<span>5000</span>或<span>10000</span>）条<span>&nbsp;H2</span>的性能要好于<span>SQLite</span>。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">插入性能：性能差不多快，<span>SQLite</span>略快。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">更新性能：更新一条记录<span>&nbsp;SQLite</span>的性能好于<span>H2</span>。更新多条记录（有索引），<span>SQLite</span>【<span>0.04s</span>】的性能要好于<span>H2</span>【<span>0.18s</span>】</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">删除性能：删除一条记录<span>.SQLite</span>【非常小】的性能略好于<span>H2</span>【非常小】。删除多条记录，<span>SQLite</span>【<span>0.078s</span>】好于<span>H2</span>的【<span>0.12s</span>】</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">启动时间：都比较快</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">并发性能：<span>H2</span>的查询支持一定的并发性，要强于<span>SQLite</span>。更新和插入，基本上都没有并发可言。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">总的看来，<span>SQLite</span>的性能要好于<span>H2</span>，但并发性不如。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">另外<span>SQLite</span>一般使用<span>C</span>的<span>API</span>接口访问，而<span>H2</span>支持<span>JDBC</span>。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">并且都可以大多数主流平台上</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">对于<span>C\C++\C#</span>应用而言，使用<span>SQLite</span>是更好的选择。对于<span>Java</span>应用，<span>H2</span>是不错的选择。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">奇怪的两点：</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">在无索引查询单条数据，<span>SQLite</span>的性能【<span>0.375s</span>】要比<span>H2</span>【<span>6.9s</span>】要快非常多。(原因发现是H2使用Big Long效率差了好多，比起Int)</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: small">在无索引查询多条数据，<span>SQLite</span>的性能甚至比有索引时还好快一些？？？？。而有索引情况下<span>H2</span>查询多条数据也好于<span>SQLite</span></span></p><img src ="http://www.cppblog.com/ming81/aggbug/184371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:58 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(六)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184369.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:57:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184369.html</guid><description><![CDATA[<h2><span style="font-size: large"><span>6.<span>&nbsp;&nbsp;</span></span>性能测试</span></h2>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">下面分别对<span>SQLite</span>和<span>H2</span>进行了性能测试</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h4><span style="font-size: large">6.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: large"><span>SQLite</span>测试方案</span></h4>
<h5><span style="font-size: large"><span>6.1.1<span>&nbsp;&nbsp;&nbsp;</span></span>测试环境</span></h5>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>主机：<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>操作系统：<span>&nbsp;&nbsp;&nbsp;&nbsp;Windows XP;</span></span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 21pt; margin: 0cm 0cm 0pt 42pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small"><span>CPU</span>：<span>&nbsp;&nbsp;&nbsp;&nbsp;Intel Dual 2.2GHZ;</span></span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 21pt; margin: 0cm 0cm 0pt 42pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">内存：<span>&nbsp;&nbsp;&nbsp;&nbsp;1.99GB</span>内存</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>测试目标版本：<span>SQLite 3.6.12</span></span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<h5><span style="font-size: large"><span>6.1.2<span>&nbsp;&nbsp;&nbsp;</span></span>测试数据</span></h5>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 21pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">测试数据库表<span>ip_table</span>结构如下</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<table style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; border-collapse: collapse; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<tbody>
<tr>
<td style="padding-bottom: 0cm; background-color: silver; padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm; background-origin: initial; background-clip: initial" width="114">
<p style="text-align: center; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">字段名</span></strong></p></td>
<td style="padding-bottom: 0cm; background-color: silver; padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="114">
<p style="text-align: center; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">类型</span></strong></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Id(PK)</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Integer</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Dst_ip</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Varchar(20)</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Agent_ip</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Varchar(20)</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Dst_mac</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Varchar(20)</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Dst_port</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Integer</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Dst_vlan</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Varchar(20)</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 85.2pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="114">
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr></tbody></table>
<h5><span style="font-size: large"><span>6.1.2<span>&nbsp;&nbsp;&nbsp;</span></span>测试过程</span></h5>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 21pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">使用<span>C++</span>编写了测试工程，启动测试程序后，先分别插入<span>50000</span>条和<span>1000000</span>条数据，然后执行一系列的测试</span></p>
<h5><span style="font-size: large"><span>6.1.3<span>&nbsp;&nbsp;&nbsp;</span></span>测试结果</span></h5>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<table style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: auto auto auto 10.5pt; letter-spacing: normal; border-collapse: collapse; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<tbody>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18.05pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold">用例名</strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18.05pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold">5w</strong><strong style="font-weight: bold">（条）单个线程</strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18.05pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold">100w</strong><strong style="font-weight: bold">（条）单个线程</strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18.05pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold">100w</strong><strong style="font-weight: bold">（条）<span>10个并发线程</span></strong></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">初始插入时间</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">45s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">初始插入时间（不加索引）</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">1.782s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">38.109s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">插入<span>1条记录</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.0016s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">插入<span>1000条记录</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.047s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.047s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.453s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">插入<span>1000条记录（无索引）</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.6s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">1s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">11.39s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询一条记录</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.0033s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询一条记录<span>(不使用索引)</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.016s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.375s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.859s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询<span>1000条记录</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.016s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.391s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.828s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询<span>1000条记录(不使用索引)</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.015s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.375s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.906s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询全部记录分组统计<span>Group by</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.688s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">15.473s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询<span>1000&nbsp;条（结果排序 ）</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.031s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.39s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.453s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">查询所有记录（结果排序）</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.766s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">16.203s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">33.594s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">更新一条记录</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.0043s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">更新一条记录（不使用索引）</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.016s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.359s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.719s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">更新<span>10000条数据</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.062s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.047s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">更新<span>10000条数据（无索引）</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.016s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.375s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">2.719s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">删除一条数据</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">100纳秒以内</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.0041s</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">删除一条条数据（无索引）</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.125s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">5.047s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">删除<span>10000条数据</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.078s</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">0.078s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 142.1pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="189">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">删除<span>10000条数据（无索引）</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 81pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="108">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">79-125ms</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 90pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="120">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">5.031s</p></td>
<td style="padding-bottom: 0cm; background-color: rgb(166,166,166); border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 72pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm; background-origin: initial; background-clip: initial" width="96">
<p style="padding-bottom: 0px; text-indent: 18pt; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr></tbody></table>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0cm 0cm 0pt 10.5pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">结论：</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLlite</span><span style="font-size: small">内存数据库的处理速度很快；</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLlite</span><span style="font-size: small">内存数据库在查找数据时有索引的情况下，查询、更新、删除速度快；</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLlite</span><span style="font-size: small">内存数据库并发性比较差，可以认为并发能力为<span>0</span>；</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLlite</span><span style="font-size: small">内存数据库占用内存空间，<span>100w</span>条数据在<span>40M</span>左右（创建单个索引，<span>6</span>个字段）</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">针对数据流探针来说，<span>5w</span>条数据<span>SQLlite</span>归并的速度在<span>0.688s</span>，可以尝试将部分功能用数据库归并实现。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLLite</span><span style="font-size: small">支持自定义函数，效率没有测试，应该和他提供的<span>API</span>效率差不多</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span><span style="font-size: small">7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">SQLLite</span><span style="font-size: small">支持复合<span>sql</span>语句</span></p><img src ="http://www.cppblog.com/ming81/aggbug/184369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:57 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(五)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184368.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:56:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184368.html</guid><description><![CDATA[<h2><span style="font-size: large"><span>5.</span>内存数据库之比较</span></h2>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">上述内存数据库，首先由于<span>License</span>限制，排除了所有的商业数据库产品包括：</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">Alitibase</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">Oralce Berkelay DB</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">Oracle TimesTen</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">eXtrmeDB</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">还包括<span>&nbsp;Berkelay DB</span>这样的开源，但限制商业使用的数据库。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="font-size: small">所以比较的重点就是<span>SQLite</span>和<span>H2</span></span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<table style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">
<tbody>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">方面</span></strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">具体要求</span></strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">必要条件</span></strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small"><span>SQLite</span></span></strong></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small"><span>H2</span></span></strong></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">License</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是否收费</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">免费使用</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">免费使用</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是否开源</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">开源</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">开源</span></p></td></tr>
<tr style="height: 10.35pt">
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是否有技术支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">主要是社区支持，如果需要专业支持需要购买</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">主要是社区支持，如果需要专业支持需要购买</span></p></td></tr>
<tr style="height: 10.35pt">
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">商业目的的分发版本是否仍要收费</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">免费</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">免费</span></p></td></tr>
<tr style="height: 10.35pt">
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">其他</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; height: 10.35pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">性能</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">数据容量支持<span>100000</span>条以上记录</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">并发查询处理能力</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span>SQLite</span>在并发（包括多进程和多线程）读写方面的性能一直不太理想。数据库可能会被写操作独占，从而导致其它读写操作阻塞或出错。</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">并发性较好（在模拟器中有使用，支持<span>50</span>个并发查询没问题）</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">查询速度</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">数据量少的情况非常好</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">修改速度</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">平台支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>32/64</span>位</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">全部支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">全部支持（需<span>java</span>平台支持）</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">Linux/window/UNIX/mobile</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>Linux/Mac OS/Windows</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">全部支持（需<span>java</span>平台支持）</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">运行方式支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持嵌入式</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持独立运行</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">不支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">连接方式支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>ODBC</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">不支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>JDBC</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">必须通过第三方的<span>JDBC</span>驱动</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持内存访问</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">通过<span>c</span>接口（专用<span>API</span>）</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">通过<span>JDBC</span>，不支持<span>API</span>访问</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持网络访问</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">不支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>SQL</span>支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>SQL</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">是</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>Index</span>，<span>Trigger</span>，</span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>Constrains</span>，<span>Views</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持，有资料说其不支持外键约束。</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 48.6pt; padding-right: 5.4pt; font-size: 1em; padding-top: 0cm" width="65">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">管理界面</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持管理界面</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>CLI</span></span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持<span>Web</span>界面的管理控制台</span></p></td></tr>
<tr>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 108pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="144">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">管理界面友好程度</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 27pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="36">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 126pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="168">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">较差</span></p></td>
<td style="padding-bottom: 0cm; background-color: transparent; border-top-color: rgb(233,233,233); padding-left: 5.4pt; width: 117pt; padding-right: 5.4pt; font-size: 1em; border-left-color: rgb(233,233,233); padding-top: 0cm" width="156">
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">较好</span></p></td></tr></tbody></table>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p><img src ="http://www.cppblog.com/ming81/aggbug/184368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:56 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(四)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184367.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:55:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184367.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 4.5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;H2 Database&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h2是Thomas Mueller提供的一个开源的、纯java实现的关系数据库，官方网站：http://www.h2database.com/html/...&nbsp;&nbsp;<a href='http://www.cppblog.com/ming81/archive/2012/07/20/184367.html'>阅读全文</a><img src ="http://www.cppblog.com/ming81/aggbug/184367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:55 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(三）</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184364.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:11:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184364.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: （上接内存数据库介绍4.1SQLite）4.1.2&nbsp;&nbsp;&nbsp;哪些场合适合使用其他的关系型数据库管理系统（RDBMS）&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;客户端/服务器程序如果你有许多的客户端程序要通过网络访问一个共享的数据库,&nbsp;你应当考虑用一个客户端/服务器数据库来替...&nbsp;&nbsp;<a href='http://www.cppblog.com/ming81/archive/2012/07/20/184364.html'>阅读全文</a><img src ="http://www.cppblog.com/ming81/aggbug/184364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:11 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(二)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184362.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184362.html</guid><description><![CDATA[<h2><span>
<h2>4.<span> </span>常用内存数据库</h2>
<h4><span style="font-size: large">4.1<span> SQLite</span></span></h4>
<p style="padding-bottom: 0px; text-indent: 10.5pt; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>SQLite</span>是一个小型的<span>C</span>程序库，实现了独立的，可嵌入的，零配置的<span>SQL</span>数据库引擎。特性包括：</span></p>
<ul style="padding-bottom: 0px; margin: 0px 0px 1.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">事务操作是原子，一致，孤立，并且持久的<span>(ACID)</span>，即使在系统崩溃和电源故障之后。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">零配置<span>&#8212;&#8212;</span>不需要安装和管理。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">实现了绝大多数<span>SQL92</span>标准。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">整个数据库存储在一个单一的文件中。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">数据库文件可以在不同字节序的机器之间自由地共享。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">支持最大可达<span>2T</span>的数据库。<span> (2</span></span><sup><span style="font-size: 10pt">41</sup><span style="font-size: small"> </span></span><span style="font-size: small">字节<span>)</span></span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">字符串和<span>BLOB</span>类型的大小最大可达<span> 2G </span>字节<span>(2</span></span><sup><span style="font-size: 10pt">31</span></sup><span style="font-size: small">字节<span>)</span>。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">小的代码： 完整配置的少于<span>250KB</span>，忽略一些可选特性的少于<span>150KB</span>。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">在大多数常见操作上比流行的客户<span>/</span>服务器数据库引擎<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlite.org/speed.html" target="_blank"><span>更快</span></a>。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">简单，易于使用的<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlite.org/capi3.html" target="_blank"><span style="color: windowtext; text-decoration: none"><span>API</span></a></span>。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">内建<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlite.org/tclsqlite.html" target="_blank"><span style="color: windowtext; text-decoration: none"><span>TCL</span><span>绑定</span></a></span>。 <a style="color: rgb(16,138,198); text-decoration: underline" href="http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers" target="_blank"><span>另外提供</span></a>可用于许多其他语言的绑定。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">具有良好注释的源代码，<span>95%</span>经过测试。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">独立：没有外部依赖。</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">源代码位于<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlite.org/copyright.html" target="_blank"><span>公共域</span></a>。 可用于任何用途。</span></li></ul>
<p style="padding-bottom: 0px; text-indent: 10.5pt; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>SQLite</span>发行版包含一个独立的命令行访问程序<span>(<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlitecn.org/sqlite.html"><span style="color: windowtext; text-decoration: none">sqlite</span></a>)</span>，可用于管理<span>SQLite</span>数据库，并适合作为一个如何使用<span>SQLite</span>库的例子。</span></p>
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; text-indent: 10.5pt; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>License:<span> SQLite</span></span>使用<span>Public domain</span>授权（注），对于个人使用和商业使用都是免费的。</span></p>
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">技术上的优点和特性<br /><span>SQLite</span><span>是一个轻量级、跨平台的关系型数据库。</span></span></p>
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><br /><span style="font-size: small">&#9671;轻量级</span></p>
<p style="padding-bottom: 0px; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">先说它的第一个特色：轻量级。想必<span>SQLite</span>的作者很看重这个特性，连它的<span>Logo</span>都是用的<span>&#8220;</span>羽毛<span>&#8221;</span>，来显摆它的轻飘飘。<span>SQLite</span>和<span>C/S</span>模式的数据库软件不同，它是进程内的数据库引擎，因此不存在数据库的客户端和服务器。使用<span>SQLite</span>一般只需要带上它的一个动态库，就可以享受它的全部功能。而且那个动态库的尺寸也挺小，以版本<span>3.6.11</span>为例，<span>Windows</span>下<span>487KB</span>、<span>Linux</span>下<span>347KB</span>。</span></p>
<p style="padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">&#9671; </span><span style="font-size: small">绿色软件</span></p>
<p style="padding-bottom: 0px; text-indent: 10.5pt; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><span>SQLite</span>的另外一个特点是绿色：它的核心引擎本身不依赖第三方的软件，使用它也不需要<span>&#8220;</span>安装<span>&#8221;</span>。所以在部署的时候能够省去不少麻烦。</span><span><br /></span><br /><span style="font-size: small">&#9671;单一文件</span></p>
<p style="padding-bottom: 0px; text-indent: 10.5pt; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">所谓的<span>&#8220;</span>单一文件<span>&#8221;</span>，就是数据库中所有的信息（比如表、视图、触发器、等）都包含在一个文件内。这个文件可以<span>copy</span>到其它目录或其它机器上，也照用不误。</span><br /><br /></p>
<p style="padding-bottom: 0px; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">&#9733;技术上的缺点和不足</span><br /><br /><span style="font-size: small">&#9671;并发访问的锁机制</span><br /><span style="font-size: small">SQLite</span><span style="font-size: small">在并发（包括多进程和多线程）读写方面的性能一直不太理想。数据库可能会被写操作独占，从而导致其它读写操作阻塞或出错。</span><br /><br /><span style="font-size: small">SQL</span><span style="font-size: small">标准支持不全</span><br /><span style="font-size: small">在它的<a style="color: rgb(16,138,198); text-decoration: underline" href="http://www.sqlite.org/omitted.html" target="_blank"><span>官方网站</span></a>上，具体列举了不支持哪些<span>SQL92</span>标准。我个人感觉比较不爽的是不支持外键约束。</span><br /><br /><span style="font-size: small">&#9671;网络文件系统（以下简称<span>NFS</span>）</span><br /><span style="font-size: small">有时候需要访问其它机器上的<span>SQLite</span>数据库文件，就会把数据库文件放置到网络共享目录上。这时候你就要小心了。当<span>SQLite</span>文件放置于<span>NFS</span>时，在并发读写的情况下可能会出问题（比如数据损坏）。原因据说是由于某些<span>NFS</span>的文件锁实现上有<span>Bug</span>。</span><br /><br /><span style="font-size: small">&#9733;编程语言接口</span><br /><span style="font-size: small">SQLite</span><span style="font-size: small">支持很多种语言的编程接口。这对于我这种喜欢混用多种编程语言的人来说，是很爽的。下面我大概介绍一下。</span><br /><br /><span style="font-size: small">&#9671;</span><span style="font-size: small"><span>C/C++<br /></span>由于<span>SQLite</span>本身是<span>C</span>写的，它<a style="color: rgb(16,138,198); text-decoration: underline" href="http://www.sqlite.org/cintro.html" target="_blank"><span>自带的</span><span style="color: windowtext; text-decoration: none">API</span></a>也是<span>C</span>接口的。所以<span>C/C++</span>用起来最直接了。假如你不喜欢面向过程的<span>C API</span>风格，可以另外找个<span>C++</span>的包装库。想重新发明轮子的同学，也可以自己包装一个。</span><br /><span style="font-size: small">&#9671;</span><span style="font-size: small"><span>Java<br /></span>如果要用<span>Java</span>访问<span>SQLite</span>，可以通过<span>SQLite</span>的<span>JDBC</span>驱动，或者通过专门的<span>SQLite</span>包装库。我个人建议走<span>JDBC</span>方式，万一将来要换数据库，代码就不用大改。</span><br /><span style="font-size: small">&#9671;</span><span style="font-size: small">Python<br /><a style="color: rgb(16,138,198); text-decoration: underline" href="http://www.pysqlite.org/" target="_blank"><span style="color: windowtext; text-decoration: none"><span style="font-size: small">pysqlite</span></span></a></span><span style="font-size: small">是<span>Python</span>操作<span>SQLite</span>的首选。从<span>Python 2.5</span>开始，它已经被整合到<span>Python</span>的标准库中。看来<span>Python</span>社区还是蛮喜欢<span>SQLite</span>嘛。</span><br /><span style="font-size: small">&#9671;</span><span style="font-size: small"><span>.Net<br /></span>对于喜欢<span>.Net</span>的同学，可以通过<span>SQLite</span>的<a style="color: rgb(16,138,198); text-decoration: underline" href="http://sqlite.phxsoftware.com/" target="_blank"><span style="color: windowtext; text-decoration: none"><span>ADO.NET</span></a></span>驱动来访问。</span><br /><span style="font-size: small">&#9671;</span><span style="font-size: small"><span>Ruby<br />Ruby</span>可以通过<a style="color: rgb(16,138,198); text-decoration: underline" href="http://rubyforge.org/projects/sqlite-ruby/" target="_blank"><span style="color: windowtext; text-decoration: none"><span>SQLite-Ruby</span></a></span>操作<span>SQLite</span>数据库，不过我没用过。</span><br /><span style="font-size: small">&#9671;</span><span style="font-size: small"><span>Perl<br /></span>在<span>CPAN</span>上有<a style="color: rgb(16,138,198); text-decoration: underline" href="http://search.cpan.org/search?module=DBD::SQLite" target="_blank"><span style="color: windowtext; text-decoration: none"><span>DBD::SQLite</span></a></span>，不过我也没用过。</span><br /><br /><span style="font-size: small">&#9733;一些非技术的参考因素</span></p>
<p style="padding-bottom: 0px; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">需要根据<span>&#8220;<span><a style="color: rgb(16,138,198); text-decoration: underline" href="http://program-think.blogspot.com/2009/02/how-to-choose-opensource-project.html" target="_blank"><span>如何选择开源项目</span></a></span>&#8221;</span>里面提到的几个参考因素，再评估一下。</span><br /><span style="font-size: small">&#9671;授权协议（<span>License</span>）</span><br /><span style="font-size: small">SQLite</span><span style="font-size: small">使用的是<a style="color: rgb(16,138,198); text-decoration: underline" href="http://en.wikipedia.org/wiki/Public_domain" target="_blank"><span style="color: windowtext; text-decoration: none"><span>Public Domain</span></a></span>协议，这是最爽一种，可以放心大胆地用。</span><br /><span style="font-size: small">&#9671;用户的普及程度</span><br /><span style="font-size: small">最近这几年，使用<span>SQLite</span>的人越来越多。包括一些大公司也开始把它整合到产品中（比如<span>Google</span>的<span>Gears</span>、<span>Apple</span>的<span>Safari</span>、<span>Adobe</span>的<span>AIR</span>）。</span><br /><span style="font-size: small">&#9671;开发的活跃程度</span><br /><span style="font-size: small">如果到<span>SQLite</span>的<a style="color: rgb(16,138,198); text-decoration: underline" href="http://www.sqlite.org/changes.html" target="_blank"><span>Change Log</span></a>上大致了解一下，可以看出最近<span>5</span>年基本上每<span>1-2</span>个月都会有更新。说明开发的活跃度还是非常高的。</span><br /><br /></p>
<p style="padding-bottom: 0px; margin: 0cm 0cm 6pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">SQLite<span style="font-size: 10.5pt">不同于其他大部分的SQL数据库引擎,因为它的首要设计目标就是简单化:</span></span></p>
<ul style="padding-bottom: 0px; margin: 0px 0px 1.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">易于管理</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">易于使用</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">易于嵌入其他大型程序</span></li><li style="text-align: left; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">易于维护和配置</span></li></ul>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">许多人喜欢<span>SQLite因为它的小巧和快速. 但是这些特性只是它的部分优点, 使用者还会发现SQLite是非常稳定的. 出色的稳定性源于它的简单, 越简单就越不容易出错. 除了上述的简单、小巧和稳定性外, 最重要的在于SQLite力争做到简单化.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">简单化在一个数据库引擎中可以说是一个优点<span>, 但也可能是个缺点, 主要决定于你想要做什么. 为了达到简单化, SQLite省略了一些人们认为比较有用的特性, 例如高并发性、 严格的存取控制、丰富的内置功能、 存储过程、复杂的SQL语言特性、 XML以及Java的扩展, 超大的万亿级别的数据测量等等. 如果你需要使用上述的这些特性并且不介意它们的复杂性, 那么SQLite也许就不适合你了. SQLite没有打算作为一个企业级的数据库引擎, 也并不打算和Oracle或者PostgreSQL竞争.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">仅凭经验来说<span>SQLite适用于以下场合: 当你更看中简单的管理、使用和维护数据库, 而不是那些企业级数据库提供的不计其数的复杂功能的时候，使用SQLite是一个比较明智的选择. 事实也证明, 人们在许多情况下已经清楚的认识到简单就是最好的选择.</span></span></p>
<h5><span style="font-size: large"><span>4.1.1<span> </span>SQLite</span>最佳试用场合</span></h5>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>网站</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">作为数据库引擎<span>SQLite适用于中小规模流量的网站(也就是说, 99.9%的网站). SQLite可以处理多少网站流量在于网站的数据库有多大的压力. 通常来说, 如果一个网站的点击率少于100000次/天的话, SQLite是可以正常运行的. 100000次/天是一个保守的估计, 不是一个准确的上限. 事实证明, 即使是10倍的上述流量的情况下SQLite依然可以正常运行</span><span style="font-size: small">.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>嵌入式设备和应用软件</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">因为<span>SQLite数据库几乎不需要管理, 因此对于那些无人值守运行或无人工技术支持的设备或服务, SQLite是一个很好的选择. SQLite能很好的适用于手机, PDA, 机顶盒, 以及其他仪器. 作为一个嵌入式数据库它也能够很好的应用于客户端程序.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>应用程序文件格式</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">SQLite<span style="font-size: 10.5pt">作为桌面应用程序的本地磁盘文件格式取得了巨大成功.例如金融分析工具、CAD 包、档案管理程序等等. 一般的数据库打开操作需要调用sqlite3_open()函数，并且标记一个显式本地事务的起始点（BEGIN TRANSACTION）来保证以独占的方式得到文件的内容. 文件保存将执行一个提交（COMMIT）同时标记另一个显式本地事务起始点. 这种事务处理的作用就是保证对于应用程序数据文件的更新是原子的、持久的、独立的和一致的.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">数据库里可以加入一些临时的触发器<span>,用来把所有的改变记录在一张临时的取消/重做日志表中. 当用户按下取消/重做按钮的时候这些改变将可以被回滚. 应用这项技术实现一个无限级的取消/重做功能只需要编写很少的代码.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>替代某些特别的文件格式</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">许多程序使用<span>fopen(), fread(), 或 fwrite()函数创建和管理一些自定义的文件用来保存数据. 使用SQLite替代这些自定义的文件格式将是一种很好的选择.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>内部的或临时的数据库</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">对于那些有大量的数据需要用不同的方式筛选分类的程序<span>, 相对于编写同样功能的代码, 如果你把数据读入一个内存中的SQLite数据库, 然后使用连接查询和ORDER BY子句按一定的顺序和排列提取需要的数据, 通常会更简单和快速. 按照上述的方法使用内嵌的SQLite数据库将会使程序更富有灵活性, 因为添加新的列或索引不用重写任何查询语句.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>命令行数据集分析工具</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">有经验的<span>SQL用户可以使用SQLite命令行程序去分析各种混杂的数据集. 原是数据可以从CSV（逗号分隔值文件）文件中导入, 然后被切分产生无数的综合数据报告. 可能得用法包括网站日志分析, 运动统计分析, 编辑规划标准, 分析试验结果.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">当然你也可以用企业级的客户端<span>/服务器数据库来做同样的事情. 在这种情况下使用SQLite的好处是: SQLite的部署更为简单并且结果数据库是一个单独的文件, 你可以把它存储在软盘或者优盘或者直接通过email发给同事.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>在<span>Demo或测试版的时候作为企业级数据库的替代品</span></p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">如果你正在编写一个使用企业级数据库引擎的客户端程序<span>, 使用一个允许你连接不同SQL数据库引擎的通用型数据库后台将是很有意义的. 其更大的意义在于将SQLite数据库引擎静态的连接到客户端程序当中，从而内嵌SQLite作为混合的数据库支持. 这样客户端程序就可以使用SQLite数据库文件做独立的测试或者验证.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>数据库教学</p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">因为<span>SQLite的安装和使用非常的简单(安装过程几乎忽略不计, 只需要拷贝SQLite源代码或sqlite.exe可执行文件到目标主机, 然后直接运行就可以) 所以它非常适合用来讲解SQL语句. 同学们可以非常简单的创建他们喜欢的数据库, 然后通过电子邮件发给老师批注或打分. 对于那些感兴趣怎样实现一个关系型数据库管理系统（RDBMS）的高层次的学生, 按照模块化设计且拥有很好的注释和文档的SQLite源代码, 将为他们打下良好的基础. 这并不是说SQLite就是如何实现其他数据库引擎的精确模型, 但是很适合学生们了解SQLite是如何快速工作的, 从而掌握其他数据库系统的设计实现原则.</span></span></p>
<p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10pt">&#183;<span> </span></span>试验<span>SQL语言的扩展</span></p>
<p style="padding-bottom: 0px; margin: 0px 0px 0px 36pt; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: 10.5pt">SQLite<span style="font-size: 10.5pt">简单且模块化的设计使得它可以成为一个用来测试数据库语言特性或新想法的优秀的原型平台.</span></span></p></span></h2> <img src ="http://www.cppblog.com/ming81/aggbug/184362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:06 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)常用内存数据库介绍(一)</title><link>http://www.cppblog.com/ming81/archive/2012/07/20/184361.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 20 Jul 2012 08:02:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/20/184361.html</guid><description><![CDATA[<h2><span style="font-size: large"><span>1.<span>&nbsp;&nbsp;</span></span>内存数据库简介</span></h2>
<h4><span style="font-size: large"><span>1.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>概念</span></h4>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 21.1pt; margin: 0cm 0cm 6pt 21pt; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><strong style="font-weight: bold"><span style="font-size: small">一、什么是内存数据库</span></strong><span style="font-size: small"><span>&nbsp;<br /><br /></span>传统的数据库管理系统把所有数据都放在磁盘上进行管理，所以称做磁盘数据库（<span>DRDB:Disk-Resident Database</span>）。磁盘数据库需要频繁地访问磁盘来进行数据的操作，由于对磁盘读写数据的操作一方面要进行磁头的机械移动，另一方面受到系统调用（通常通过<span>CPU</span>中断完成，受到<span>CPU</span>时钟周期的制约）时间的影响，当数据量很大，操作频繁且复杂时，就会暴露出很多问题。</span><span style="font-size: small"><span>&nbsp;<br /><br /><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></span>近年来，内存容量不断提高，价格不断下跌，操作系统已经可以支持更大的地址空间（计算机进入了<span>64</span>位时代），同时对数据库系统实时响应能力要求日益提高，充分利用内存技术提升数据库性能成为一个热点。</span><span style="font-size: small"><span>&nbsp;<br /><br /><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></span>在数据库技术中，目前主要有两种方法来使用大量的内存。一种是在传统的数据库中，增大缓冲池，将一个事务所涉及的数据都放在缓冲池中，组织成相应的数据结构来进行查询和更新处理，也就是常说的共享内存技术，这种方法优化的主要目标是最小化磁盘访问。另一种就是内存数据库<span>(MMDB:Main Memory Database</span>，也叫主存数据库<span>)</span>技术，就是干脆重新设计一种数据库管理系统，对查询处理、并发控制与恢复的算法和数据结构进行重新设计，以更有效地使用<span>CPU</span>周期和内存，这种技术近乎把整个数据库放进内存中，因而会产生一些根本性的变化。两种技术的区别如下表：</span></p>
<p style="text-align: center; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/ming81/46114a59-5cf5-3a15-a7f6-62a3c602daa8.jpg" width="480" longdesc="" height="480" /><br /><br />　　内存数据库系统带来的优越性能不仅仅在于对内存读写比对磁盘读写快上，更重要的是，从根本上抛弃了磁盘数据管理的许多传统方式，基于全部数据都在内存中管理进行了新的体系结构的设计，并且在数据缓存、快速算法、并行操作方面也进行了相应的改进，从而使数据处理速度一般比传统数据库的数据处理速度快很多，一般都在<span>10倍以上，理想情况甚至可以达到1000倍。&nbsp;<br /><br />　　而使用共享内存技术的实时系统和使用内存数据库相比有很多不足，由于优化的目标仍然集中在最小化磁盘访问上，很难满足完整的数据库管理的要求，设计的非标准化和软件的专用性造成可伸缩性、可用性和系统的效率都非常低，对于快速部署和简化维护都是不利的。</span></p>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;</p>
<h2><span style="font-size: large"><span>2.<span>&nbsp;&nbsp;</span></span>内存数据库历史和发展</span></h2>
<p style="text-align: left; padding-bottom: 0px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一、雏形期<span style="font-size: 10pt"><br /></span>从上个世纪<span style="font-size: 10pt">60</span>年代末到<span style="font-size: 10pt">80</span>年代初。在这个时期中，出现了主存数据库的雏形。<span style="font-size: 10pt">1969</span>年<span style="font-size: 10pt">IBM</span>公司研制了世界上最早的数据库管理系统<span style="font-size: 10pt">------</span>基于层次模型的数据库管理系统<span style="font-size: 10pt">IMS</span>，并作为商品化软件投入市场。在设计<span style="font-size: 10pt">IMS</span>时，<span style="font-size: 10pt">IBM</span>考虑到基于内存的数据管理方法，相应推出了<span style="font-size: 10pt">IMS/VS Fast Path</span>。<span style="font-size: 10pt">Fast Path</span>是一个支持内存驻留数据的商业化数据库，但它同时也可以很好地支持磁盘驻留数据。在这个产品中体现了主存数据库的主要设计思想，也就是将需要频繁访问，要求高响应速度的数据直接存放在物理内存中访问和管理。在这个阶段中，包括网状数据库、关系数据库等其他各种数据库技术也都逐渐成型。<span style="font-size: 10pt">&nbsp;<br /></span>二、技术理论成熟期<span style="font-size: 10pt"><br />1984</span>年，<span style="font-size: 10pt">D J DeWitt</span>等人发表了《主存数据库系统的实现技术》一文。第一次提出了<span style="font-size: 10pt">Main Memory Database</span>（主存数据库）的概念。预言当时异常昂贵的计算机主存价格一定会下降，用户有可能将大容量的数据库全部保存在主存中，提出了<span style="font-size: 10pt">AVL</span>树、哈希算法、主存数据库恢复机制等主存数据库技术的关键理论，为主存数据库的发展指出了明确的方向<span style="font-size: 10pt">&nbsp;</span>。<span style="font-size: 10pt"><br />1984</span>年，<span style="font-size: 10pt">D J DeWitt</span>等人提出使用非易逝内存或预提交和成组提交技术作为主存数据库的提交处理方案，使用指针实现主存数据库的存取访问。<span style="font-size: 10pt"><br />1985</span>年，<span style="font-size: 10pt">IBM</span>推出了<span style="font-size: 10pt">IBM 370</span>上运行的<span style="font-size: 10pt">OBE</span>主存数据库<span style="font-size: 10pt">&nbsp;<br />1986</span>年，<span style="font-size: 10pt">RB Hagman</span>提出了使用检查点技术实现主存数据库的恢复机制。威斯康星大学提出了按区双向锁定模式解决主存数据库中的并发控制问题。并设计出<span style="font-size: 10pt">MM-DBMS</span>主存数据库。贝尔实验室推出了<span style="font-size: 10pt">DALI</span>主存数据库模型。<span style="font-size: 10pt">&nbsp;<br />1987</span>年，<span style="font-size: 10pt">ACM SIGMOD</span>会议中提出了以堆文件（<span style="font-size: 10pt">HEAP FILE</span>）作为主存数据库的数据存储结构。<span style="font-size: 10pt">Southern Methodist</span>大学设计出<span style="font-size: 10pt">MARS</span>主存数据库模型。<span style="font-size: 10pt"><br />1988</span>年普林斯顿大学设计出<span style="font-size: 10pt">TPK</span>主存数据库。<span style="font-size: 10pt">&nbsp;<br />1990</span>年普林斯顿大学又设计出<span style="font-size: 10pt">System M</span>主存数据库。<span style="font-size: 10pt"><br /></span>三、产品发展期和市场成长期<span style="font-size: 10pt"><br /></span>随着互联网的发展，越来越多的网络应用系统需要能够支持大用户量并发访问、高响应速度的的数据库系统，主存数据库市场成熟<span style="font-size: 10pt">&nbsp;<br /></span>半导体技术快速发展，半导体内存大规模生产，动态随机存取存储器（<span style="font-size: 10pt">DRAM</span>）的容量越来越大，而价格越来越低，这无疑为计算机内存的不断扩大提供了硬件基础，使得主存数据库的技术可行性逐步成熟<span style="font-size: 10pt">&nbsp;<br />1994</span>年美国<span style="font-size: 10pt">OSE</span>公司推出了第一个商业化的，开始实际应用的主存数据库产品<span style="font-size: 10pt">Polyhedra&nbsp;<br />1998</span>年德国<span style="font-size: 10pt">SoftwareAG</span>推出了<span style="font-size: 10pt">Tamino Database</span>。<span style="font-size: 10pt">&nbsp;<br />1999</span>年日本<span style="font-size: 10pt">UBIT</span>会社开发出<span style="font-size: 10pt">XDB</span>主存数据库产品。韩国<span style="font-size: 10pt">Altibase</span>推出<span style="font-size: 10pt">Altibase&nbsp;<br />2000</span>年奥地利的<span style="font-size: 10pt">QuiLogic</span>公司推出了<span style="font-size: 10pt">SQL-IMDB&nbsp;<br />2001</span>年美国<span style="font-size: 10pt">McObject</span>推出<span style="font-size: 10pt">eXtremeDB</span>。加拿大<span style="font-size: 10pt">Empress</span>公司推出<span style="font-size: 10pt">EmpressDB<br /></span>四、几种主存技术应用的比较<span style="font-size: 10pt"><br /></span>第一代：用户定制的主存数据库。通过应用程序来管理内存和数据；不支持<span style="font-size: 10pt">SQL</span>语句<span style="font-size: 10pt">,&nbsp;</span>不提供本地存储<span style="font-size: 10pt">,&nbsp;</span>没有数据库恢复技术；性能好但很难维护和在别的应用中不能使用；应用在实时领域比如工厂自动化生产。<span style="font-size: 10pt"><br /></span>第二代：简单功能的内存数据库。能够快速处理简单的查询；支持部分的<span style="font-size: 10pt">&nbsp;SQL</span>语句和简单的恢复技术；主要目的是能够快速处理大量事务；针对简单事务处理领域<span style="font-size: 10pt">,</span>尤其是交换机<span style="font-size: 10pt">,&nbsp;</span>移动通信等。<span style="font-size: 10pt"><br /></span>第三代：通用的主存数据库。针对传统的商业关系型数据库领域，能够提供更高的性能、通用性以及稳定性；提供不同的接口来处理复杂的<span style="font-size: 10pt">SQL</span>语句和满足不同的应用领域；可以应用在计费、电子商务、在线安全领域，几乎包括磁盘数据库的所有应用领域。<span style="font-size: 10pt"><br /></span>五、目前几种常见的通用内存数据库<span style="font-size: 10pt"><br />eXtremeDB</span>：<span style="font-size: 10pt">eXtremeDB</span>实时数据库是<span style="font-size: 10pt">McObject</span>公司的一款特别为实时与嵌入式系统数据管理而设计的数据库，只有<span style="font-size: 10pt">50K</span>到<span style="font-size: 10pt">130K</span>的开销，速度达到微秒级。<span style="font-size: 10pt">eXtremeDB</span>完全驻留在主内存中，不使用文件系统（包括内存盘）。<span style="font-size: 10pt">eXtremeDB</span>采用了新的磁盘融合技术，将内存拓展到磁盘，将磁盘当做虚拟内存来用，实时性能保持微秒级的同时，数据管理量在<span style="font-size: 10pt">32BIT</span>下能达到<span style="font-size: 10pt">20G</span>。<span style="font-size: 10pt"><br />Oracle TimesTen</span>：<span style="font-size: 10pt">Oracle TimesTen</span>是<span style="font-size: 10pt">Oracle</span>从<span style="font-size: 10pt">TimesTen</span>公司收购的一个内存优化的关系数据库，它为应用程序提供了实时企业和行业（例如电信、资本市场和国防）所需的即时响应性和非常高的吞吐量。<span style="font-size: 10pt">Oracle TimesTen</span>可作为高速缓存或嵌入式数据库被部署在应用程序层中，它利用标准的<span style="font-size: 10pt">&nbsp;SQL&nbsp;</span>接口对完全位于物理内存中的数据存储区进行操作。<span style="font-size: 10pt"><br />SolidDB</span>：<span style="font-size: 10pt">Solid Information Technology&nbsp;</span>成立于<span style="font-size: 10pt">&nbsp;1992&nbsp;</span>年，全球总部位于加州<span style="font-size: 10pt">Cupertino</span>，<span style="font-size: 10pt"><br />Solid</span>数据管理平台将基于内存和磁盘的全事务处理数据库引擎、载体级高可用性及强大的数据复制功能紧密地融为一体。<span style="font-size: 10pt"><br />Altibase</span>：<span style="font-size: 10pt">ALTIBASE</span>公司从<span style="font-size: 10pt">1999</span>年就一直致力于内存数据库软件和其应用的开发，提供高性能和高可用性的软件解决方案。特别适合通信、网上银行、证券交易、实时应用和嵌入式系统领域。目前占据<span style="font-size: 10pt">80%</span>以上内存数据库市场，可以说是当今数据库软件技术的领导者。目前<span style="font-size: 10pt">Altibase</span>在国内成功案例也比较多，尤其是在电信行业，已经得到了广泛认可。</p> <img src ="http://www.cppblog.com/ming81/aggbug/184361.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-20 16:02 <a href="http://www.cppblog.com/ming81/archive/2012/07/20/184361.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Memcached深度分析</title><link>http://www.cppblog.com/ming81/archive/2012/07/19/184253.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Thu, 19 Jul 2012 15:47:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/19/184253.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Memcached是danga.com（运营LiveJournal的技术团队）开发的一套分布式内存对象缓存系统，用于在动态系统中减少数据库负载，提升性能。关于这个东西，相信很多人都用过，本文意在通过对memcached的实现及代码分析，获得对这个出色的开源软件更深入的了解，并可以根据我们的需要对其进行更进一步的优化。末了将通过对BSM_Memcache扩展的分析，加深对memcached的使用方式...&nbsp;&nbsp;<a href='http://www.cppblog.com/ming81/archive/2012/07/19/184253.html'>阅读全文</a><img src ="http://www.cppblog.com/ming81/aggbug/184253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-19 23:47 <a href="http://www.cppblog.com/ming81/archive/2012/07/19/184253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos代码阅读(一)</title><link>http://www.cppblog.com/ming81/archive/2012/07/13/183170.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Fri, 13 Jul 2012 05:49:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2012/07/13/183170.html</guid><description><![CDATA[<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">Mangos<strong style="line-height: 22px; font-weight: bold">有13个工程。</strong></font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><strong style="line-height: 22px; font-weight: bold"><font style="line-height: normal" color="#000000">使用了4个外部工具库，分别是：</font></strong></p>
<ol style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">跨平台的网络通讯框架</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.cse.wustl.edu/~schmidt/ACE.html"><font style="line-height: normal" color="#000000">The<span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span><em style="line-height: 22px">ADAPTIVE Communication Environment</em><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>(<em style="line-height: 22px">ACE</em>)</font></a></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">压缩库</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.zlib.net/"><em style="line-height: 22px"><font style="line-height: normal" color="#000000">zlib</font></em></a></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">Socket通信库<span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span></font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.alhem.net/Sockets/index.html"><font style="line-height: normal" color="#000000">C++ Sockets Library</font></a><font style="line-height: normal" color="#000000"><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>(使用在realmd工程中，和使用在Mangosd工程中的RASocket，负责处理Remote Administration。其他地方没有使用到这个</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.alhem.net/Sockets/index.html"><font style="line-height: normal" color="#000000">C++ Sockets Library</font></a><font style="line-height: normal" color="#000000"><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>）。发现在</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.alhem.net/Sockets/index.html"><font style="line-height: normal" color="#000000">C++ Sockets Library</font></a><font style="line-height: normal" color="#000000">的TcpSocket::Open中存在一个问题，在n = connect(s, ad, ad);语句执行后，如果n=-1，</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.alhem.net/Sockets/index.html"><font style="line-height: normal" color="#000000">C++ Sockets Library</font></a><font style="line-height: normal" color="#000000">会检测是否ERR为WSAEWOULDBLOCK，否则表示成功，但在动态库中使用TcpSocket的时候，我发现n = connect(s, ad, ad);语句执行后，n=-1，ERR会为0，这个时候连接也是成功了，但TcpSocket::Open会当做不成功处理。我发现这个问题，但没有时间去探究原因，也许并不是一个问题。</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">C++的并行编程模板库</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.threadingbuildingblocks.org/"><font style="line-height: normal" color="#000000">Threading Building Blocks</font></a><font style="line-height: normal" color="#000000"><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>（tbb 和 tbbmalloc）</font></li></ol>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">Mangos的实现分为：登录服务器（realmd）和世界服务器（mangosd+game）。realmd和mangos共用了Mangos公共库（shared）。</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000"><font style="line-height: normal">工程</font><strong style="line-height: 22px; font-weight: bold"><font style="line-height: normal">shared</font></strong></font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">提供了通用功能，包括了数据库的封装类，实现了对MySql的访问，同样，我们可以编写派生类来支持其他的数据库。</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000"><font style="line-height: normal">工程</font><strong style="line-height: 22px; font-weight: bold"><font style="line-height: normal">script</font></strong></font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">提供了脚本接口，并实现了简单的几个脚本，封装为DLL，提供给game使用，具体可参考：</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://hi.baidu.com/theredhat/blog/item/f111174f6f8c8c36afc3ab96.html"><font style="line-height: normal" color="#000000">MaNGOS脚本接口</font></a><font style="line-height: normal" color="#000000">。</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">通过使用不同的脚本DLL来替换Mangos中的AI实现,可以让game具有更强的AI。ScriptDev2 就是一个这样的库。ScriptDev2 is a replacement for the Script Library that comes with MaNGOS(</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.getmangos.com/"><font style="line-height: normal" color="#000000"><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>http://www.getmangos.com</font></a><font style="line-height: normal" color="#000000"><span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span>) written in C++ and is compatible with Windows and Linux. It provides scripts for NPCs, Boss events, and Items currently. Once ScriptDev2 is compiled it is automatically run by MaNGOS on server startup.</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="https://wsfuhw.bay.livefilestore.com/y1mxKIW4-MlOSI69ygpy__ZbG-liBFrIxwi90qW98u5CJn8iPnKYP43hPx1pThVu2UaPTl1HF11wLVIWnrjvU4C9Ixmtg_qejtc89ynsdPN8dfC_Rmv-0iNbDVWN-W-hf9_CHf2z24u1ijfQl3gBpO0iQ/image[8].png" rel="WLPP"><font style="line-height: normal" color="#000000"><img style="line-height: 22px; border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="https://wsfuhw.bay.livefilestore.com/y1mqFJsXeSbhabwV6AbfzaxEFJu7HHpFQ19ZZ2xgmMiGNpK61hWRoXnQaUiP173L2bea7a6xYc0c4iqbEVe43wz2vW0U5UesrKiAuDvpZ-FjKQDf41SxlZ_VGFVE12JuMEzo0YMjb6D9NhDa3fDwh0qNQ/image_thumb[3]%20126B330F.png" width="815" height="301" /></font></a></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000"><font style="line-height: normal">工程</font><strong style="line-height: 22px; font-weight: bold"><font style="line-height: normal">mangosd</font></strong></font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">mangos是世界服务器的管理器，负责初始化工作和启动世界服务器各层的线程，这些工作主要是由类Master来实现。具体是：</font></p>
<ol style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">使用三个数据库对象WorldDatabase和CharacterDatabase和loginDatabase，初始化三大数据库：World Database和Character Database和login Database，并为每个数据库的访问都启动一个DB delay threads。具体的数据库操作功能都是由Mangos公共库shared来提供。</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">调用sWorld.SetInitialWorldSettings，对World进行初始化，包括加载所有的游戏数据和初始化各种更新定时器和邮件定时器，还有些其他的初始化工作。类World的成员函数SetInitialWorldSettings调用成员函数LoadConfigSettings解析mangosd.conf，解析后内容放入uint32 m_configs[CONFIG_VALUE_COUNT]中。</font> 
<ol style="line-height: 22px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">加载的游戏数据有：</font> 
<ol style="line-height: 22px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">DBC数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">Objects数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">Spells数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">Pooling数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">Game Event数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">loot数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">技能数据</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">所有其他的游戏数据，包括Waypoints和Trainers等等等。</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">脚本数据</font></li></ol></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">初始化的更新定时器有：</font> 
<ol style="line-height: 22px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_OBJECTS</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_SESSIONS</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_AUCTIONS</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_WEATHERS</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_UPTIME</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_CORPSES</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">WUPDATE_EVENTS</font></li></ol></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">其他的初始化工作有:</font> 
<ol style="line-height: 22px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">初始化MapManager，启动Map System</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">初始化Battlegrounds，启动BattleGround System</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">初始化DailyQuestResetTime</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">初始化sGameEventMgr，Starting Game Event system</font></li></ol></li></ol></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">类Master还实现了mangos server的退出管理</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">类Master启动WorldRunnable，开始游戏逻辑。Heartbeat for the World，由Master创建，并设置线程为最高优先级。</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">类Master启动CliRunnable：Command Line Interface handling thread，由Master创建。CliRunnable运行时候会生成一个WorldDatabase线程，在接收到输入后会调用sWorld.QueueCliCommand把Cmd放入到World::cliCmdQueue中。</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">类Master启动RARunnable：Remote Administration，由Master创建</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">如果配置要求，类Master还会启动一个freeze catcher thread</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">类Master启动2个网络线程ReactorRunnable（可配置数目）</font></li></ol>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000"><strong style="line-height: 22px; font-weight: bold">mangosd</strong>的线程总共有（1+3+1+1+1+2 +1 =10）10个线程。</font></p>
<ol style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">主线程Master</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">2个网络线程ReactorRunnable（可配置数目）（网络层）</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">一个World线程（逻辑层）</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">三个DB线程（数据层）</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">一个CLI线程（输入层），运行时候会生成一个WorldDatabase线程</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">一个RA线程（管理层）</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">一个freeze catcher 线程（可选）</font></li></ol>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">工程g3dlite：游戏逻辑层的底层库</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">工程framework：系统框架</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000"><font style="line-height: normal">工程</font><font style="line-height: normal"><strong style="line-height: 22px; font-weight: bold">realm</strong></font></font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">负责登陆和选择游戏服务器，进行负载均衡。用到了</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.alhem.net/Sockets/index.html"><font style="line-height: normal" color="#000000">C++ Sockets Library</font></a><font style="line-height: normal" color="#000000">进行登录处理，采用select I/O模型。实现了</font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://blog.csdn.net/jq0123/archive/2009/04/10/4062020.aspx"><font style="line-height: normal" color="#000000">Wow, Mangos登录时的SRP6认证</font></a><font style="line-height: normal" color="#000000">。客户端作为它的client连接到realm server认证和选择了mangos server就断开。 而mangos server和realm server则不进行连接，只是通过数据库交互数据：mangos server把自己的状态和拥有的角色数放入库中。realm server会读取数据库中的这些信息来获知mangos server的状态。</font></p>
<ol style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">数据库realm的realmlist表保存了realm的列表</font></li><li style="line-height: 22px; margin: 0px 0px 3px"><font style="line-height: normal" color="#000000">realm通过如下事件处理函数来负责登陆和选择游戏服务器。</font> 
<p style="line-height: 22px; margin: 0px 0px 1.35em"><font style="line-height: normal" color="#000000">const AuthHandler table[] =<br style="line-height: 22px" />{<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { AUTH_LOGON_CHALLENGE,&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleLogonChallenge&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { AUTH_LOGON_PROOF,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleLogonProof&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &amp;AuthSocket::_HandleReconnectChallenge},<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { AUTH_RECONNECT_PROOF,&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleReconnectProof&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { REALM_LIST,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS_AUTHED,&nbsp;&nbsp;&nbsp; &amp;AuthSocket::_HandleRealmList&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { XFER_ACCEPT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleXferAccept&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { XFER_RESUME,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleXferResume&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br style="line-height: 22px" />&nbsp;&nbsp;&nbsp; { XFER_CANCEL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS_CONNECTED, &amp;AuthSocket::_HandleXferCancel&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="line-height: 22px" />};</font></p></li></ol>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">登录处理：</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">user登录到realm server进行身份认证，并选择登录上哪个mangos server。user登录到mangos server后，将不再和realm server交互。</font></p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 1.35em; letter-spacing: normal; font: 13px/22px Simsun; white-space: normal; orphans: 2; color: rgb(255,255,255); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><font style="line-height: normal" color="#000000">参考：<span style="line-height: normal" class="Apple-converted-space"><span class="Apple-converted-space">&nbsp;</span></span></font><a style="line-height: 22px; letter-spacing: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; color: rgb(129,165,248); font-size: 12px; cursor: pointer; font-weight: normal; text-decoration: none" href="http://www.cppblog.com/Jedimaster/archive/2006/10/14/13674.html"><font style="line-height: normal" color="#000000">Wow 服务器解析</font></a></p><img src ="http://www.cppblog.com/ming81/aggbug/183170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2012-07-13 13:49 <a href="http://www.cppblog.com/ming81/archive/2012/07/13/183170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)IOCP模型的总结</title><link>http://www.cppblog.com/ming81/archive/2011/01/25/139281.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Tue, 25 Jan 2011 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2011/01/25/139281.html</guid><description><![CDATA[<span style="FONT-SIZE: 10pt">IOCP（I/O Completion Port，I/O完成端口）是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。在处理多个并发的异步I/O请求时，以往的模型都是在接收请求是创建一个线程来应答请求。这样就有很多的线程并行地运行在系统中。而这些线程都是可运行的，Windows内核花费大量的时间在进行线程的上下文切换，并没有多少时间花在线程运行上。再加上创建新线程的开销比较大，所以造成了效率的低下。 <br><br>而IOCP模型是事先开好了N个线程，存储在线程池中，让他们hold。然后将所有用户的请求都投递到一个完成端口上，然后N个工作线程逐一地从完成端口中取得用户消息并加以处理。这样就避免了为每个用户开一个线程。既减少了线程资源，又提高了线程的利用率。 <br><br>完成端口模型是怎样实现的呢？我们先创建一个完成端口（::CreateIoCompletioPort()）。然后再创建一个或多个工作线程，并指定他们到这个完成端口上去读取数据。我们再将远程连接的套接字句柄关联到这个完成端口（还是用::CreateIoCompletionPort()）。一切就OK了。 <br><br>工作线程都干些什么呢？首先是调用::GetQueuedCompletionStatus()函数在关联到这个完成端口上的所有套接字上等待I/O的完成。再判断完成了什么类型的I/O。一般来说，有三种类型的I/O，OP_ACCEPT，OP_READ和OP_WIRTE。我们到数据缓冲区内读取数据后，再投递一个或是多个同类型的I/O即可（::AcceptEx()、::WSARecv()、::WSASend()）。对读取到的数据，我们可以按照自己的需要来进行相应的处理。 <br><br>为此，我们需要一个以OVERLAPPED（重叠I/O）结构为第一个字段的per-I/O数据自定义结构。</span> <br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;_PER_IO_DATA<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OVERLAPPED&nbsp;ol;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;重叠I/O结构&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;buf[BUFFER_SIZE];&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;数据缓冲区&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nOperationType;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">I/O操作类型&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;OP_READ&nbsp;1</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;OP_WRITE&nbsp;2</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;OP_ACCEPT&nbsp;3</span><span style="COLOR: #000000"><br>}&nbsp;PER_IO_DATA,&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">PPER_IO_DATA;&nbsp;</span></div>
<br><br><span style="FONT-SIZE: 10pt">将一个PER_IO_DATA结构强制转化成一个OVERLAPPED结构传给::GetQueuedCompletionStatus()函数，返回的这个PER_IO_DATA结构的的nOperationType就是I/O操作的类型。当然，这些类型都是在投递I/O请求时自己设置的。 <br><br>这样一个IOCP服务器的框架就出来了。当然，要做一个好的IOCP服务器，还有考虑很多问题，如内存资源管理、接受连接的方法、恶意的客户连接、包的重排序等等。以上是个人对于IOCP模型的一些理解与看法，还有待完善。另外各Winsock API的用法参见MSDN。<br><br>补充IOCP模型的实现：</span> <br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">创建一个完成端口</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">FCompletPort&nbsp;:</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateIoCompletionPort(&nbsp;INVALID_HANDLE_VALUE,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);&nbsp;<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">接受远程连接，并把这个连接的socket句柄绑定到刚才创建的IOCP上</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">AConnect&nbsp;:</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;accept(&nbsp;FListenSock,&nbsp;addr,&nbsp;len);<br>CreateIoCompletionPort(&nbsp;AConnect,&nbsp;FCompletPort,&nbsp;nil,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);&nbsp;<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">创建CPU数*2&nbsp;+&nbsp;2个线程</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;i:</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;to&nbsp;si.dwNumberOfProcessors</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"><br>begin<br>&nbsp;&nbsp;AThread&nbsp;:</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TRecvSendThread.Create(&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">&nbsp;);<br>&nbsp;&nbsp;AThread.CompletPort&nbsp;:</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;FCompletPort;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">告诉这个线程，你要去这个IOCP去访问数据</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">end;&nbsp;</span></div>
<br><br><span style="FONT-SIZE: 10pt">OK，就这么简单，我们要做的就是建立一个IOCP，把远程连接的socket句柄绑定到刚才创建的IOCP上，最后创建n个线程，并告诉这n个线程到这个IOCP上去访问数据就可以了。 <br><br>再看一下TRecvSendThread线程都干些什么：</span> <br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">procedure&nbsp;TRecvSendThread.Execute;<br>var<br>&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br>begin<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(not&nbsp;self.Terminated)&nbsp;</span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">查询IOCP状态（数据读写操作是否完成）</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;GetQueuedCompletionStatus(&nbsp;CompletPort,&nbsp;BytesTransd,&nbsp;CompletKey,&nbsp;POVERLAPPED(pPerIoDat),&nbsp;TIME_OUT&nbsp;);&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;BytesTransd&nbsp;</span><span style="COLOR: #000000">&lt;&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;&nbsp;then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">.;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">数据读写操作完成&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">再投递一个读数据请求</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;WSARecv(&nbsp;CompletKey,&nbsp;@(pPerIoDat</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">.BufData),&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;BytesRecv,&nbsp;Flags,&nbsp;@(pPerIoDat</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">.Overlap),&nbsp;nil&nbsp;);<br>&nbsp;&nbsp;end;<br>end;&nbsp;</span></div>
<br><br><span style="FONT-SIZE: 10pt">读写线程只是简单地检查IOCP是否完成了我们投递的读写操作，如果完成了则再投递一个新的读写请求。<br>应该注意到，我们创建的所有TRecvSendThread都在访问同一个IOCP（因为我们只创建了一个IOCP），并且我们没有使用临界区！难道不会产生冲突吗？不用考虑同步问题吗？<br>呵呵，这正是IOCP的奥妙所在。IOCP不是一个普通的对象，不需要考虑线程安全问题。它会自动调配访问它的线程：如果某个socket上有一个线程A正在访问，那么线程B的访问请求会被分配到另外一个socket。这一切都是由系统自动调配的，我们无需过问。</span><br>
<script type=text/javascript>
if ($ != jQuery) {
$ = jQuery.noConflict();
}
var isLogined = false;
var cb_blogId = 32508;
var cb_entryId = 1089306;
var cb_blogApp = "baoli";
var cb_blogUserGuid = "f68a3d0b-63cf-dd11-9e4d-001cf0cd104b";
var cb_entryCreatedDate = '2008/3/3 22:05:00';
</script>
<img src ="http://www.cppblog.com/ming81/aggbug/139281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2011-01-25 15:36 <a href="http://www.cppblog.com/ming81/archive/2011/01/25/139281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)实现基于DNS的负载均衡</title><link>http://www.cppblog.com/ming81/archive/2011/01/19/138918.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 19 Jan 2011 12:24:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2011/01/19/138918.html</guid><description><![CDATA[<p style="FONT-SIZE: 10pt">如果你有一个很受欢迎的Web站点，你会发现当请求的连接数增加时，服务器的响应延时也会随之增加。虽然你可以增加RAM、升级处理器、使用更快的驱动器及总线,这在短期内会有一定的帮助，但最终会发现一台服务器无法完成需要的任务。<br>&nbsp;<br>使用多台服务器平衡负载是一个不错的想法，你可以在你的服务器池中随意增加多台服务器来提高服务器的性能和增强网络的稳定性。如果你的服务器池中有多台服务器，当一台down机后，其他服务器可以接替它的工作，继续提供服务而不至于造成服务中断。<br>&nbsp;<br>通过使用RR-DNS（Round-Robin Domain Name System）可以实现平衡负载的功能，向一个主机名发出的入站请求可以被转发到多个IP地址上。<br>&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;<br>在BIND9中实现此功能就向添加一条A记录那么简单。举例说，如果我们向somode.com区域文件中加入下面行便可实现：<br>www&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 60&nbsp;&nbsp;&nbsp;&nbsp; IN&nbsp;&nbsp;&nbsp;&nbsp; A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 220.181.11.124<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 60&nbsp;&nbsp;&nbsp;&nbsp; IN&nbsp;&nbsp;&nbsp;&nbsp; A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 220.181.11.125<br>&nbsp;<br>当然你还可以根据需要加入更多服务器。这样如果有人请求解析[url]www.somode.com[/url]时将有一半的机率解析到220.181.11.124上，而另一半会解析到220.181.11.125上。<br>&nbsp;<br>然而，使用RR-DNS方法实现负载平衡也会带来一些问题：<br>第一，域名服务器是一个分布式系统，是按照一定的层次结构组织的。当用户将域名解析请求提交给本地的域名服务器，它会因不能直接解析而向上一级域名服务器提交，上一级域名服务器再依次向上提交，直到RR-DNS 域名服务器把这个域名解析到其中一台服务器的IP 地址。可见，从用户到RR-DNS 间存在多台域名服务器，而它们都会缓冲已解析的名字到IP 地址的映射,这会导致该域名服务器组下所有用户都会访问同一Web 服务器，出现不同Web 服务器间的负载不平衡。为了保证在域名服务器中域名到IP 地址的映射不被长久缓冲，RR-DNS 在域名到IP 地址的映射上设置一个TTL(Time To Live)值，过了这一段时间，域名服务器将这个映射从缓冲中淘汰。当用户请求，它会再向上一级域名服务器提交请求并进行重新映射。这就涉及到如何设置这个TTL值，若这个值太大，在这个TTL 期间，很多请求会被映射到同一台Web 服务器上，同样会导致负载不平衡。若这个值太小，例如是０，会导致本地域名服务器频繁地向RR-DNS提交请求，增加了域名解析的网络流量，同样会使RR-DNS 成为系统中一个新的瓶颈。<br>&nbsp;<br>第二，用户机器会缓冲从名字到IP 地址的映射，而不受TTL 值的影响，用户的访问请求会被送到同一台Web 服务器上。由于用户访问请求的突发性和访问方式不同，例如有的人访问一下就离开了，而有的人访问可长达几个小时，所以各台服务器间的负载仍存在倾斜（Skew）而不能控制。假设用户在每个会话中平均请求数为20，负载最大的服务器获得的请求数额高于各服务器平均请求数的平均比率超过百分之三十。也就是说，当TTL 值为0 时，因为用户访问的突发性也会存在着较严重的负载不平衡。<br>&nbsp;<br>第三，系统的可靠性和可维护性不好。若一台服务器失效，会导致将域名解析到该服务器的用户看到服务中断，即使用户按&#8220;Reload&#8221;按钮，也无济于事。系统管理员也不能随时地将一台服务器切出服务进行维护，如进行操作系统和应用软件升级，这需要修改RR-DNS 服务器中的IP 地址列表，把该服务器的IP 地址从中划掉，然后等上一段时间，等所有域名服务器将该域名到这台服务器的映射淘汰，和所有映射到这台服务器的客户机不再使用该站点为止。<br>&nbsp;<br>RR-DNS方法只是一个简单的负载平衡方案，如果你有更高要求，可以研究LVS集群（IPVS和KTCPVS、TCPHA），实现基于IP的负载均衡和基于内容的负载均衡。</p>
<img src ="http://www.cppblog.com/ming81/aggbug/138918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2011-01-19 20:24 <a href="http://www.cppblog.com/ming81/archive/2011/01/19/138918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos源码分析（4）：服务器结构探讨之继续世界服</title><link>http://www.cppblog.com/ming81/archive/2011/01/19/138911.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 19 Jan 2011 11:24:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2011/01/19/138911.html</guid><description><![CDATA[<span style="FONT-SIZE: 10pt">　　都已经看出来了，这种每切换一次地图就要重新连接服务器的方式实在是不够优雅，而且在实际游戏运营中也发现，地图切换导致的卡号，复制装备等问题非常多，这里完全就是一个事故多发地段，如何避免这种频繁的连接操作呢？<br><br><br><br>　　最直接的方法就是把那个图倒转过来就行了。客户端只需要连接到中心服上，所有到地图服务器的数据都由中心服来转发。很完美的解决方案，不是吗？<br><br>　　这种结构在实际的部署中也遇到了一些挑战。对于一般的MMORPG服务器来说，单台服务器的承载量平均在2000左右，如果你的服务器很不幸地只能带1000人，没关系，不少游戏都是如此；如果你的服务器上跑了3000多玩家依然比较流畅，那你可以自豪地告诉你的策划，多设计些大量消耗服务器资源的玩法吧，比如大型国战、公会战争等。<br><br>　　2000人，似乎我们的策划朋友们不大愿意接受这个数字。我们将地图服务器分开来原来也是想将负载分开，以多带些客户端，现在要所有的连接都从中心服上转发，那连接数又遇到单台服务器的可最大承载量的瓶颈了。<br><br>　　这里有必要再解释下这个数字。我知道，有人一定会说，才带2000人，那是你水平不行，我随便写个TCP服务器都可带个五六千连接。问题恰恰在于你是随便写的，而MMORPG的服务器是复杂设计的。如果一个演示socket API用的echo服务器就能满足MMOG服务器的需求，那写服务器该是件多么惬意的事啊。<br><br>　　但我们所遇到的事实是，服务器收到一个移动包后，要向周围所有人广播，而不是echo服务器那样简单的回应；服务器在收到一个连接断开通知时要向很多人通知玩家退出事件，并将该玩家的资料写入数据库，而不是echo服务器那样什么都不需要做；服务器在收到一个物品使用请求包后要做一系列的逻辑判断以检查玩家有没有作弊；服务器上还启动着很多定时器用来更新游戏世界的各种状态......<br><br>　　其实这么一比较，我们也看出资源消耗的所在了：服务器上大量的复杂的逻辑处理。再回过头来看看我们想要实现的结构，我们既想要有一个唯一的入口，使得客户端不用频繁改变连接，又希望这个唯一入口的负载不会太大，以致于接受不了多少连接。<br><br>　　仔细看一看这个需求，我们想要的仅仅只是一台管理连接的服务器，并不打算让他承担太多的游戏逻辑。既然如此，那五六千个连接也还有满足我们的要求。至少在现在来说，一个游戏世界内，也就是一组服务器内同时有五六千个在线的玩家还是件让人很兴奋的事。事实上，在大多数游戏的大部分时间里，这个数字也是很让人眼红的。<br><br>　　什么？你说梦幻、魔兽还有史先生的那个什么征途远不止这么点人了！噢，我说的是大多数，是大多数，不包括那些明星。你知道大陆现在有多少游戏在运营吗？或许你又该说，我们不该在一开始就把自己的目标定的太低！好吧，我们还是先不谈这个。<br><br>　　继续我们的结构讨论。一般来说，我们把这台负责连接管理的服务器称为网关服务器，因为内部的数据都要通过这个网关才能出去，不过从这台服务器提供的功能来看，称其为反向代理服务器可能更合适。我们也不在这个名字上纠缠了，就按大家通用的叫法，还是称他为网关服务器吧。<br><br>　　网关之后的结构我们依然可以采用之前描述的方案，只是，似乎并没有必要为每一个地图都开一个独立的监听端口了。我们可以试着对地图进行一些划分，由一个Master Server来管理一些更小的Zone Server，玩家通过网关连接到Master Server上，而实际与地图有关的逻辑是分派给更小的Zone Server去处理。<br><br>　　最后的结构看起来大概是这样的：<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; Zone Server&nbsp; &nbsp;&nbsp;&nbsp;Zone Server<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;/<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; \&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;/<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Master Server&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; Master Server<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; /<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;/<br>Gateway Server&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;\&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &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; /<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;/<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;|&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Center Server<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;|<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;|<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Client</span> 
<img src ="http://www.cppblog.com/ming81/aggbug/138911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2011-01-19 19:24 <a href="http://www.cppblog.com/ming81/archive/2011/01/19/138911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos源码分析（15）：游戏对象的实现</title><link>http://www.cppblog.com/ming81/archive/2011/01/19/138910.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 19 Jan 2011 11:23:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2011/01/19/138910.html</guid><description><![CDATA[<span style="FONT-SIZE: 10pt">狭义的游戏对象是指游戏世界中所能看到及可交互的对象，如玩家、怪物、物品等，我们这里也主要讨论这类对象在服务器上的组织及实现。<br>　　在大部分的MMOG中，游戏对象的类型都大同小异，主要有物品、生物、玩家等。比如在wow中，通过服务器发下来的GUID我们可以了解到，游戏中有9大类对象，包括物品(Item)、背包(Container)、生物(Unit)、玩家(Player)、游戏对象(GameObject)、动态对象(DynamicObject)、尸体(Corpse)等。<br><br>　　在mangos的实现中，对象使用类继承的方式，由Object基类定义游戏对象的公有接口及属性，包括GUID的生成及管理、构造及更新UpdateData数据的虚接口、设置及获取对象属性集的方法等。然后分出了两类派生对象，一是Item，另一是WorldObject。Item即物品对象，WorldObject顾名思义，为世界对象，即可添加到游戏世界场景中的对象，该对象类型定义了纯虚接口，也就是不可被实例化，主要是在Object对象的基础上又添加了坐标设置或获取的相关接口。<br><br>　　Item类型又派兵出了一类Bag对象，这是一种特殊的物品对象，其本身具有物品的所有属性及方法，但又可作为新的容器类型，并具有自己特有的属性和方法，所以实现上采用了派生。mangos在实现时对Bag的类型定义做了点小技巧，Item的类型为2，Bag的类型为6，这样在通过位的方式来表示类型时，Bag类型也就同时属于Item类型了。虽然只是很小的一个技巧，但在很多地方却带来了极大的便利。<br><br>　　从WorldObject派生出的类型就有好几种了，Unit、GameObject、DynamicObject和Corpse。Unit为所有生物类型的基类，同WorldObject一样，也不可被实例化。它定义了生物类型的公有属性，如种族、职业、性别、生命、魔法等，另外还提供了相关的一些操作接口。游戏中实际的生物对象类型为Creature，从Unit派生，另外还有一类派生对象Player为玩家对象。Player与Creature在实现上最大的区别是玩家的操作由客户端发来的消息驱动，而Creature的控制是由自己定义的AI对象来驱动，另外Player内部还包括了很多的逻辑系统实现。<br><br>　　另外还有两类特殊的Creature，Pet和Totem，其对象类型仍然还是生物类，只是实现上与会有些特殊的东西需要处理，所以在mangos中将其作为独立的派生类，只是实现上的一点处理。另外在GameObject中也实现有派生对象，最终的继承关系图比较简单，就不麻烦地去画图了。<br><br>　　从我所了解的早期游戏实现来看，大部分的游戏对象结构都是采用的类似这种方式。可能与早期对面向对象的理解有关，当面向对象的概念刚出来时，大家认为继承就是面向对象的全部，所以处处皆对象，处处皆继承。<br><br>　　类实现的是一种封装，虽然从云风那里出来的弃C++而转投C的声音可能会影响一部分人，但是，使用什么语言本身就是个人喜好及团队整体情况决定的。我们所要的也是最终的实现结果，至于中间的步骤，完全看个人。还是用云风的话说，这只是一种信仰问题，我依然采用我所熟悉的C++，下面的描述也是如此。<br><br>　　随着面向对象技术的深入，以及泛型等概念的相继提出，软件程序结构方面的趋势也有了很大改变。C++大师们常说的话中有一句是这样说的，尽是采用组合而不是继承。游戏对象的实现也有类似的转变，趋向于以组合的方式来实现游戏对象类型，也就是实现一个通用的entity类型，然后以脚本定义的方式组合出不同的实际游戏对象类型。<br><br>　　描述的有些抽象，具体实现下一篇来仔细探讨下。<br><br>在游戏编程精粹四有三篇文章讲到了实体以及实体管理的实现方案，其中一篇文章说到了实体管理系统的四大要素：定义实体怎样沟通的实体消息，实现一实体类代码和数据的实体代码，维护已经注册在案的实体类列表，和用来创建、管理、发送消息的实体管理器。<br><br>　　关于实体消息的内容之前讨论事件机制的时候做过一点说明，其实这也就是按接口调用和按消息驱动的区别，现在mangos的做法是完全的接口调用，所以引擎内部就没有任何的实体消息。实体代码实现和实体管理器是我们重点要讨论的内容。<br><br>　　另有一篇文章也提到了使用类继续的方式实现游戏对象的两大问题，一是它要求系统中的所有对象都必须从一个起点衍生而成，也就是说所有对象类在编译的时候已经确定，这可能是一个不受欢迎的限制，如果开发者决定添加新的对象类，则必须要对基类有所了解，方能支持新类。另一个问题在于所有的对象类都必须实现同样的一些底层函数。<br><br>　　对于第二个问题，可以通过接口继承的方式来避免基类的方法太多。在mangos的实现中就采用了类似的方法，从Object虚基类派生的Unit和WorldObject仍然还是不可实例化的类，这两种对象定义了不同的属性和方法，分来实现不同类型的对象。在游戏内部可以根据对象的实际类型来Object指针向下转型为Unit或WorldObject，以调用需要的接口。方法虽然不够OO，也还能解决问题。但是第一个问题是始终无法避免的。<br><br>　　所以我们便有了通用实体这么一个概念，其主要方法是将原来基类的接口进行分类，分到一个个不同的子类中，然后以对象组合的方式来生成我们所需要的实际游戏对象类型。这个组合的过程可以通过脚本定义的方式，这样便可以在运行时生成为同的对象类型，也就解决了上面提到的第一个问题。<br><br>　　通用实体的实现方法在目前的游戏引擎及开源代码中也可以看到影子。一个是BigWorld，从提供的资料来看，其引擎只提供了一个entity游戏对象，然后由游戏内容实现者通过xml和python脚本来自由定义不同类型的entity类型，每种类型可有不同的property和不同的方法。这样原来由基类定义的接口完全转移到脚本定义，具有非常强的灵活性。<br><br>　　另外还有一个是CEL中的entity实现。按照CEL的描述，entity可以是游戏中的任意对象，包括玩家可交互的对象，如钥匙、武器等，也可以包括不能直接交互的对象，如游戏世界，甚至任务链中的一部分等。entity本身并没有任何特性，具体的功能实现需要靠附加property来完成。简单来说，property才定义了entity可以做什么，至于该怎么做，那又是依靠behavior来定义。所以，最终在CEL中一个游戏对象其实是由entity组合了多个property及多个behavior而生成的。<br><br>　　但是CEL中的property与BigWorld中的property意义不大一样，在CEL中可定义的property其实是引擎内部要先提供的，比如其示例中所举的pcobject.mesh、pcmove.linear、pctools.inventory等，而BigWorld中的property是完全的自由定制。从这个角度来讲，其实可以把CEL中的property看作是游戏的逻辑系统，也就是我们上面所描述的，接口分类后所定义的子类。<br><br>　　由引擎内部提供可选择的property与BigWorld所采用的完全自由定制property其实本质上是相同的。在用BigWorld实现的游戏中，也不可能为每种游戏对象类型都完全从头定义property，基于代码利用的原则，也会先定义一些小类，然后在entity类型定义时以自定义property的方式来包含这些小类。当然，我没有使用过BigWorld，上面的描述也只是基于游戏实现的大原则所做出来的。<br><br>　　描述的依然有些抽象，我们可以用wow及mangos代码来说明一下。mangos中为object定义了一个属性集合，根据对象类型的不同，这个属性集的大小及保存数据也会有差异，另外游戏对象内部含有处理不同游戏逻辑的系统，如RestSystem、FloodFilterSystem、VariousSystem等等，在player.h中以接口组的方式进行定义。<br><br>　　如果要将这种结构改为我们描述的通用entity系统，可以让object只提供property注册和删除的接口，这里的property定义与CEL中的相同，放在mangos中也就是上面说的RestSystem、FloodFilterSystem、VariousSystem这些。然后也通过xml文件的方式定义我们所需要的游戏对象类型，如player,creature,item等，不同的对象类型可以选择加载不同的property，加载的原则是需要哪些功能就加载哪些property。<br><br>　　对象的定义按上面的方法完成后，对象的实现也需要做一些修改。以前客户端的消息是直接交由player来处理，AI也是直接调用creature的接口来完成一些功能，现在通用的entity内部已经没有任何可用的方法，所有的实现都转到了property中，所以需要由各个property实现自己来注册感兴趣的事件及消息，entity实现一个消息的转发，转给对此感兴趣的property来处理。其余的实现就没有什么不同了。<br><br>　　当然，我们再做一点扩展，让property不光由引擎来提供，用脚本本身也能定义property，并且可以通过xml来注册这些property，这样便实现了与BigWorld一样的完全自由特性。这其实也就是将很多用C++实现的功能转移到了python中，这种做法可作为参考，但不一定对所有人合适，至少在我看来，这样的实现也基本只能由程序员来做，所以让程序员选择自己最擅长的语言可能会更易于开发和调试。<br><br>有关游戏对象实现的描述，前面两篇文章中说的不甚清楚，主要是一直都要引用网上能够找到的资料来进行描述，以避免与公司引起不必要的麻烦。所以语言有些拼凑的感觉，举的例子也很不恰当，今天正好看到了游戏编程精粹五和六上的两篇文章，内容都差不多，&lt;&lt;基于组件的对象管理&gt;&gt;和&lt;&lt;基于组件的游戏对象系统&gt;&gt;，说的也是我上两篇文章想要描述的内容，所以再补一篇，引用其中的部分文字进行明确的说明。<br><br><br><br>　　传统的游戏对象管理系统采用继承的方式来实现，例如，所有的子类都从CObject派生。大多数情况下，直接派生的也是抽象类，其中带一些功能而另一些子类则不带这些功能，比如可控制/不可控制，可动画/不可动画等。mangos的实现中基本就是这种情况，从Object直接派生的Unit和WorldObject都是不可直接实例化的类。<br><br>　　传统方法的问题在于无法应对需求的变化，如要求武器也有动画效果时就无法处理了。如果硬要是这样做，那随着需求的啬，很多的方法会被放到基类中，最终的结果是继承树变得越来越头重脚轻，这样的类会丧失它的内聚性，因为它们试图为所有对象完成所有的事。<br><br>　　就是说到最后，基类会有一个很长的接口列表，而很多的游戏对象类型根本不需要实现其中的一些甚至大部分接口，但是按照这种结构却又必须去实现。以至于于实现一个非常庞大的对象，而且想要修改一点功能会导致系统的大调整。<br><br>　　我们希望的系统是可以将现有的功能组合到新的对象中，并且在将新的功能添加到现有的对象中时不需要重构大量的代码和调整继承树的结构。<br><br>　　实现的方法就是从组件来创建一个对象。组件是一个包含所有相关数据成员和方法的类，它完成某个特定的任务。把几个组件组合在一起就可以创建一个新的对象。如把Entity组件、Render组件和Collectable组件组合在一起生成了一个Spoon对象。Entity组件让我们可以把对象放到游戏世界中，Render组件让我们可以为对象指定一个模型进行渲染，而Collectable组件让我们可以拾取这个对象。<br><br>　　关于组件的实现，所有的组件都从一个基础组件接口派生，可称其为IComponent。每个组件也有自己的接口定义，并且这个接口也需要从IComponent派生，类似于这样：IComponent -- ICmpRender -- CCmpRender<br><br>　　这里的每个组件也就是我在上一篇中所说的由引擎提供的属性，或者说在BigWorld中自己实现然后定义的属性，或者使用mangos中的定义，就是一个个的System，虽然mangos并没有将其完全做成组件，但是通过其代码注释可以看到，接口也是按功能组进行了分类，如果要拆分成组件也是比较方便的。<br><br>　　组件之间的通信有两种方法，一是用组件ID查询到组件接口指针，然后调用接口方法；二是使用消息的方式，向对象中所有组件发消息。在初始化的时候，每一个组件类型都会告诉对象管理器应该接收什么样的消息。<br><br>　　查询接口的方法也就是直接的方法调用，只不过接口不是全部在基类中，所以必须先查询到指定的组件然后才能调用其接口。消息的使用前面已经说过多次，其实现方案也有过说明。<br><br>　　最后是关于游戏对象功能的扩展和游戏对象的定义。需要扩展功能也就是需要实现一个新的组件，或者修改现在组件。在大多数情况下，扩展都不会引起结构的很大调整，受影响的最多只是使用到该组件的部分代码。<br><br>　　游戏对象定义可采用完全数据驱动的方式，使用xml或者脚本语言来定义对象类型，以及每个类型需要加载的组件。对象类型注册到对象管理器后，由管理器提供创建指定类型的对象的方法。数据驱动的方式能够让策划自由定义游戏对象类型，并且随时可自由创建新的对象类型。</span> 
<img src ="http://www.cppblog.com/ming81/aggbug/138910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2011-01-19 19:23 <a href="http://www.cppblog.com/ming81/archive/2011/01/19/138910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(搬运工)Mangos源码分析（13）：再谈登录服的实现 </title><link>http://www.cppblog.com/ming81/archive/2011/01/19/138908.html</link><dc:creator>点点滴滴</dc:creator><author>点点滴滴</author><pubDate>Wed, 19 Jan 2011 11:18:00 GMT</pubDate><guid>http://www.cppblog.com/ming81/archive/2011/01/19/138908.html</guid><description><![CDATA[<span style="FONT-SIZE: 10pt">关于登录服、大区服及游戏世界服的结构之前已做过探讨，这里再把各自的职责和关系列一下。<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GateWay/WorldServer&nbsp; &nbsp;GateWay/WodlServer&nbsp;&nbsp;LoginServer LoginServer DNSServer WorldServerMgr<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;|<br>&nbsp; &nbsp;&nbsp; &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;|<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;internet<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;|<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; clients<br><br>&nbsp; &nbsp; 其中DNSServer负责带负载均衡的域名解析服务，返回LoginServer的IP地址给客户端。WorldServerMgr维护当前大区内的世界服列表，LoginServer会从这里取世界列表发给客户端。LoginServer处理玩家的登录及世界服选择请求。GateWay/WorldServer为各个独立的世界服或者通过网关连接到后面的世界服。<br><br>&nbsp; &nbsp; 在mangos的代码中，我们注意到登录服是从数据库中取的世界列表，而在wow官方服务器中，我们却会注意到，这个世界服列表并不是一开始就固定，而是动态生成的。当每周一次的维护完成之后，我们可以很明显的看到这个列表生成的过程。刚开始时，世界列表是空的，慢慢的，世界服会一个个加入进来，而这里如果有世界服当机，他会显示为离线，不会从列表中删除。但是当下一次服务器再维护后，所有的世界服都不存在了，全部重新开始添加。<br><br>&nbsp; &nbsp; 从上面的过程描述中，我们很容易想到利用一个临时的列表来保存世界服信息，这也是我们增加WorldServerMgr服务器的目的所在。GateWay/WorldServer在启动时会自动向WorldServerMgr注册自己，这样就把自己所代表的游戏世界添加到世界列表中了。类似的，如果DNSServer也可以让LoginServer自己去注册，这样在临时LoginServer时就不需要去改动DNSServer的配置文件了。<br><br>&nbsp; &nbsp; WorldServerMgr内部的实现很简单，监听一个固定的端口，接受来自WorldServer的主动连接，并检测其状态。这里可以用一个心跳包来实现其状态的检测，如果WorldServer的连接断开或者在规定时间内未收到心跳包，则将其状态更新为离线。另外WorldServerMgr还处理来自LoginServer的列表请求。由于世界列表并不常变化，所以LoginServer没有必要每次发送世界列表时都到WorldServerMgr上去取，LoginServer完全可以自己维护一个列表，当WorldServerMgr上的列表发生变化时，WorldServerMgr会主动通知所有的LoginServer也更新一下自己的列表。这个或许就可以用前面描述过的事件方式，或者就是观察者模式了。<br><br>&nbsp; &nbsp; WorldServerMgr实现所要考虑的内容就这些，我们再来看看LoginServer，这才是我们今天要重点讨论的对象。<br><br>&nbsp; &nbsp; 前面探讨一些服务器公共组件，那我们这里也应该试用一下，不能只是停留在理论上。先从状态机开始，前面也说过了，登录服上的连接会有两种状态，一是帐号密码验证状态，一是服务器列表选择状态，其实还有另外一个状态我们未曾讨论过，因为它与我们的登录过程并无多大关系，这就是升级包发送状态。三个状态的转换流程大致为：<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;LogonState -- 验证成功 -- 版本检查 -- 版本低于最新值 -- 转到UpdateState<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;|<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; -- 版本等于最新值 -- 转到WorldState<br><br>&nbsp; &nbsp; 这个版本检查的和决定下一个状态的过程是在LogonState中进行的，下一个状态的选择是由当前状态来决定。密码验证的过程使用了SRP6协议，具体过程就不多做描述，每个游戏使用的方式也都不大一样。而版本检查的过程就更无值得探讨的东西，一个if-else即可。<br><br>&nbsp; &nbsp; 升级状态其实就是文件传输过程，文件发送完毕后通知客户端开始执行升级文件并关闭连接。世界选择状态则提供了一个列表给客户端，其中包括了所有游戏世界网关服务器的IP、PORT和当前负载情况。如果客户端一直连接着，则该状态会以每5秒一次的频率不停刷新列表给客户端，当然是否值得这样做还是有待商榷。<br><br>&nbsp; &nbsp; 整个过程似乎都没有值得探讨的内容，但是，还没有完。当客户端选择了一个世界之后该怎么办？wow的做法是，当客户端选择一个游戏世界时，客户端会主动去连接该世界服的IP和PORT，然后进入这个游戏世界。与此同时，与登录服的连接还没有断开，直到客户端确实连接上了选定的世界服并且走完了排队过程为止。这是一个很必要的设计，保证了我们在因意外情况连接不上世界服或者发现世界服正在排队而想换另外一个试试时不会需要重新进行密码验证。<br><br>&nbsp; &nbsp; 但是我们所要关注的还不是这些，而是客户端去连接游戏世界的网关服时服务器该如何识别我们。打个比方，有个不自觉的玩家不遵守游戏规则，没有去验证帐号密码就直接跑去连接世界服了，就如同一个不自觉的乘客没有换登机牌就直接跑到登机口一样。这时，乘务员会客气地告诉你要先换登机牌，那登机牌又从哪来？检票口换的，人家会先验明你的身份，确认后才会发给你登机牌。一样的处理过程，我们的登录服在验明客户端身份后，也会发给客户端一个登机牌，这个登机牌还有一个学名，叫做session key。<br><br>&nbsp; &nbsp; 客户端拿着这个session key去世界服网关处就可正确登录了吗？似乎还是有个疑问，他怎么知道我这个key是不是造假的？没办法，中国的假货太多，我们不得不到处都考虑假货的问题。方法很简单，去找给他登机牌的那个检票员问一下，这张牌是不是他发的不就得了。可是，那么多的LoginServer，要一个个问下来，这效率也太低了，后面排的长队一定会开始叫唤了。那么，LoginServer将这个key存到数据库中，让网关服自己去数据库验证？似乎也是个可行的方案。<br><br>&nbsp; &nbsp; 如果觉得这样给数据库带来了太大的压力的话，也可以考虑类似WorldServerMgr的做法，用一个临时的列表来保存，甚至可以将这个列表就保存到WorldServerMgr上，他正好是全区唯一的。这两种方案的本质并无差别，只是看你愿意将负载放在哪里。而不管在哪里，这个查询的压力都是有点大的，想想，全区所有玩家呢。所以，我们也可以试着考虑一种新的方案，一种不需要去全区唯一一个入口查询的方案。<br><br>&nbsp; &nbsp; 那我们将这些session key分开存储不就得了。一个可行的方案是，让任意时刻只有一个地方保存一个客户端的session key，这个地方可能是客户端当前正连接着的服务器，也可以是它正要去连接的服务器。让我们来详细描述一下这个过程，客户端在LoginServer上验证通过时，LoginServer为其生成了本次会话的session key，但只是保存在当前的LoginServer上，不会存数据库，也不会发送给WorldServerMgr。如果客户端这时想要去某个游戏世界，那么他必须先通知当前连接的LoginServer要去的服务器地址，LoginServer将session key安全转移给目标服务器，转移的意思是要确保目标服务器收到了session key，本地保存的要删除掉。转移成功后LoginServer通知客户端再去连接目标服务器，这时目标服务器在验证session key合法性的时候就不需要去别处查询了，只在本地保存的session key列表中查询即可。<br><br>&nbsp; &nbsp; 当然了，为了session key的安全，所有的服务器在收到一个新的session key后都会为其设一个有效期，在有效期过后还没来认证的，则该session key会被自动删除。同时，所有服务器上的session key在连接关闭后一定会被删除，保证一个session key真正只为一次连接会话服务。<br><br>&nbsp; &nbsp; 但是，很显然的，wow并没有采用这种方案，因为客户端在选择世界服时并没有向服务器发送要求确认的消息。wow中的session key应该是保存在一个类似于WorldServerMgr的地方，或者如mangos一样，就是保存在了数据库中。不管是怎样一种方式，了解了其过程，代码实现都是比较简单的，我们就不再赘述了。</span> 
<img src ="http://www.cppblog.com/ming81/aggbug/138908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ming81/" target="_blank">点点滴滴</a> 2011-01-19 19:18 <a href="http://www.cppblog.com/ming81/archive/2011/01/19/138908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>