关于作者

用户名:narita1982
笔名:oいばらの泪o
地区: 北京-北京
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



博克连接

网站连接

软工连接

教程连接

访问统计:
文章个数:191
评论个数:12
留言条数:2




Powered by BlogDriver 2.1

浅睡

 

文章

Ogre 3D引擎 笔记~5 :碰撞检测

终于搞定了,郁闷,我得提高发现问题的速度>_<

物体间的碰撞检测我用的是OgreNewt(一个开源的物理引擎)。但是我不太在乎物理定律,因为作出精确的行为是需要满强的物理功底的。我只是需要用到它的碰撞检测,如何初始化等就不说了,只说下问题。

Ogre的SceneNode和OgreNewt的body是绑定的。可以用SceneNode的位置设置body的位置,或者相反。但是不要用前者,除非初始化的时候。因为不用物理规则设定body位置的话,那么碰撞就不起作用了(多么2)。

设置body的位置和方向有几种方法,setVelocity,setForce,setTorque,setOmega;分别是设置速度,受力,力矩,和角速度;因为对物理定律不熟悉,所以超级厌恶受力和力矩。所以搞一个伪物理行为取而代之:因为对物体的实际旋转没有兴趣(比如受到撞击木块会翻滚),所以只用SetVelocity调整body的位置;而用SceneNode来计算旋转方向。

具体……掠过……

注意虽然body和SceneNode是绑定的,实际上body位置或者SceneNode位置改变都是不影响到对方,必须自己改变另一个的位置。改变SceneNode的位置比较正宗的方法是用Callback,OgreNewt可以设置各种各样的Callback函数,程序会自动在某种情况发生的时候调用它们。改变位置就可以用

body->setCustomTransformCallback(customTransformCallback); 

/*定义*/

void CRider::customTransformCallback(OgreNewt::Body* me, const Ogre::Quaternion& orient, const Ogre::Vector3& pos )
{
/*获取和body绑定的指针,用body->setUserData()设定*/
 SceneNode* node=(CRider*)me->getUserData();
 node->setPosition(pos);
}

具体……掠过……

这里的callback虽然不需要传参数,但是实际上它的参数数量和形式已经是定义好的。另外,函数必须是静态的。

主要问题已经解决,我的程序因为未知原因出现了一件超级恶的事,就是body走着走着就不动了,虽然速度设置的没有错误,我想可能是物理定律发威了。搞了好久,终于发现不动的时候TransformCallback也不会被调用了,果然是物理定律发威了。Newton会将不动的物体永久打入冷宫,好像锁定一样,实际上是不再计算它。

然后发现有一个setAutoactiveCallback(),试验了一下,发现在不动的时候程序会不断调用这个callback。于是写了一个callback如下。

void CRider::customAutoActiveCallback(OgreNewt::Body* me, unsigned int state)
{
     me->unFreeze();
}

终于大功告成~~~~~~

- 作者: oいばらの泪o 2008年06月9日, 星期一 04:09  回复(0) |  引用(0) 加入博采

Ogre 3D引擎 笔记~4:玩转RibbonTrail

想作跟踪弹的尾迹?方法之一就是求助于RibbonTrail。




RibbonTrail的Demo(就是两条光绕头转动的那个)代码和注释的误导性太大。如果照抄的话,是很难作出想要的效果地。

代码其实分为几个部分:公告板(Billboard,就是永远朝向镜头的贴图)是用来作光线头部的贴图的,绑定Light是为了照到别的物体上有明暗效果,而RibbonTrail是用来作轨迹的。

那一段给节点加入Track的部分完全是误导>_<,动画的部分完全不需要。 RibbonTrail的轨迹是不需要绑定若干节点的。RibbonTrail只需要绑定两个节点,一个头,一个尾。而头必须绑定在移动的节点上,用RibbonTrail的addNode()绑定;尾则随便建一个SceneNode,用SceneNode的attachObject()绑定,这个节点的父节点会自动设置为头部,所以如果设置位移的话不要设置成世界位移。

RibbonTrail的maxElement越多,setTrailLength()越大;渐变效果越明显,最终效果也就越真实。

另外RibbonTrail的材质是一条高1pixel,宽128pixel的图。实际上白色的部分才是表示光线的部分。

嘿嘿,RibbonTrail可以作出一些很酷的效果哦。

- 作者: oいばらの泪o 2008年06月7日, 星期六 02:46  回复(1) |  引用(0) 加入博采

Ogre 3D引擎 笔记~3:摄像机绕定点转动->Overlay->RayQuery

不是很难的东西,不过想不到的话绝对可以让人吐血。

Ogre里面的转动都是自转的,所以不要改什么yaw,roll, pitch,rotate或者TS_WORLD,TS_PARENT了,即使计算部分全部自己作,它还是会傻傻地绕自己的轴转动。

看了兔子也会编游戏的月亮绕太阳公转的教程,才恍然大悟。如果公转是要转太阳,而不是月亮地。将月亮的节点绑到太阳的节点下面,月亮和太阳节点的距离是一定的,这样当太阳自传的时候,月亮就会跟着转了。

摄像机也同理。

当需要摄像机规位的时候,也不要自己想怎么rotate回去。只要将绑定摄像机的节点removeAndDestroy(),然后重新绑定就好。

用Overlay把导航条的雏形作好了。Ogre真得太脚本化了,一点技术含量也没有。
参照ExampleFrameListener写吧。Overlay的布局,字体设置,以及图片都用txt文件设置。可以在pack文件夹里把OgreCore解压缩看看。

不过不晓得Overlay动态处理图片的能力怎么样,有待研究。

用Ogre的射线查询(RayQuery)在导航板加入了显示高度的部分。有一点点飞行游戏的雏形了。活活~

RayQuery的教程还是满多的。Ogre wiki上的教程还满不错。http://www.ogre3d.org/wiki/index.php/Intermediate_Tutorial_2

具体的太都,就不写了吧 =P

- 作者: oいばらの泪o 2008年06月5日, 星期四 02:55  回复(0) |  引用(0) 加入博采

OgreNewt~1:如果不能动->Collision Tree

吐血啊,吐血……
想着“老天爷,你快让我搞定,我好去睡觉了!”,终于搞定了,老天爷真是赏脸。

查了下,有个老外和我犯了一样的错误,他花了5个小时发现的,让他狂吐;我比他吐得更厉害。心碎。

原话:I don't get it at all. It took me 5 hours to discover I had to use mNewtonWorld->setWorldSize(vector, vector) before anything would be updated.

就是说:必须调用SetWorldSize()设置世界大小,引擎才会更新。body会掉到最低处就不动了。奇怪的是,demo里没有设置,却能更新,真是害人啊。

本来想用Newton的,后来发现最大的问题是,Newton用旋转和位移,而Ogre却用translate(),yaw(), pitch() 和roll()来旋转和位移。鉴于偶数学太差,搞不定Matrix就作罢。

设置没什么难的,Newton比Ode好的地方在于Newton文档齐全,教程齐全,整合了OpenGl因此Domo可以看到效果,编译了lib和dll。OgreNewt和OgreOde一样,也需要自己编译lib,BasicFrameListener因为新版的Ogre输入部分的改动,要作一些修改。

-----------------------------------------------

OgreNewt封装得很好,Newton的Collisiton Tree只是一个框架,而OgreNewt的Collision Tree部分真的是很容易,它通过节点读取entity的mesh模型,然后读取面加入到Newton的CollisionTree里,太傻瓜了吧?一点都没有进步…… 原代码部分可以好好看下,看看怎么读Ogre的mesh模型。

- 作者: oいばらの泪o 2008年06月2日, 星期一 14:21  回复(1) |  引用(0) 加入博采

CNN对中国地震报道感动很多人

为中国骄傲

在CNN正式道歉的同时,我们也注意到了CNN与一些西方媒体在对华新闻报道上的一些变化,近日对华报道客观多了。 Mitbbs.com

CNN在四川地震后作了不少报道,其中一篇短小的新闻报道感动了许多美国人。这篇题为《中国的地震灾民忍辱负重》的新闻,报道灾区在缺少粮食、水的情况下,记者看到了地震生还者没有埋怨,他们都非常有信心地相信他们会得到政府的帮助。记者说,他看到了中国人忍辱负重,也是美国人讲的微笑着承受的精神,中国人做得很好。报道写了记者采访灾区车家窐(译音)书记的简单经过,这位年轻的书记用平静的口气,介绍了当地的受灾情况。当记者问这位书记车家窐死了多少人时,这位原先平静的书记忍不住流下了眼泪。他边流泪边告诉记者,车家窐死了500多人,这里面包括他的双亲、妻子、和两个孩子。报道最后说:正在这位书记沉浸在悲伤中时,他的报话机响了起来,这位书记向CNN记者表示抱歉,马上又投入到救灾工作中。这篇感人的报道很快被CNN放到了网站的首页上,马上吸引了众多美国人的阅读和评论。不管CNN是否有意通过这一报道向中国人民示好,但这一报道的确值得赞赏和肯定。很多美国读者看到这篇报道深受感动,表示敬佩中国人民的优良品质,也为地震受难者祈祷。

从CNN的道歉与变化,我们欣喜地看到了中国的进步。CNN主持人对中国人民恶毒攻击与污蔑,理所当然受到中国政府和中国人民的反对与抗议。中国外交部发言人前后三次严正要求CNN向中国人民道歉,CNN却置之不理。CNN的傲慢与无礼进一步激怒了海内外华人的愤慨,全球华人示威抗议之声此起彼伏,要求封杀CNN在华播放的新闻,甚至呼吁政府将CNN在华办事处驱逐出中国的声音不绝于耳。 Mitbbs.com

社会与言论的开放是一个国家与政府自信的表现。一些别有用心的西方人就常常以此攻击中国,说中国没有言论自由。这些戴着有色眼镜的西方人对中国的许多进步视而不见,甚至歪曲抵毁。其实,改革开放后的中国虽然还有不少有待改进的地方,但不可否认的是,如今中国社会与言论的开放程度前所未有。事实说明,西方国家做到的,中国做到了;西方国家做不到的,中国也可以做到。 Mitbbs.com

西方国家最反对的是中国走社会主义道路,他们千方百计处心积虑地在谋划中国和平演变,希望中国与他们那样实行西方的资本主义制度。中国的巨变,中国的开放,使西方媒体也渐渐看到了中国特色社会主义制度的优越。从这次四川地震可以看到,中国政府快速有效的应急处理措施,举国上下众志成城大力支援抗灾,就得到许多西方媒体的好评,这就是最好的说明。《纽约时报》今天有篇文章,将中国政府在四川地震的表现,与美国政府在2005年的卡特里(我来编辑特里的资料)娜飓风的救灾工作做了比较,那次救灾,美国政府的失误和缓慢遭到美国国内强烈的批评。这篇文章说,如果中国政府能比美国政府更好地处理自然灾害,那么中国体制的优越性,也许能向世人表明的不光是快速增长的经济,还展示出有效的政府能力。类似客观正面的报道,出自西方媒体之口,西方读者容易接受,比中国媒体自我宣传更具说服力。 Mitbbs.com

CNN虽然道歉了,但并不表示对中国持有偏见的西方媒体对中国的污蔑从此偃旗息鼓,改邪归正。树欲静而风不止。西方国家的某些反华政客,毫无疑问还会在很多方面给中国制造麻烦。北京奥运将在八月举行,这是中国人民企盼了一百多年的大事。尽管中国今年天灾连连,先是年初的雪灾,接着又是5.12四川大地震,多重的灾难没有使中国人民屈服,反而更加凝聚了中华民族不屈的坚强决心。中国办好奥运的决心不可动摇,中国和平崛起势不可挡。现在西方一些顽固不化的反华政客叫嚣抵制北京奥运,一些狂热的藏独份子也妄图制造事端破坏奥运。我们希望也相信,中国政府会对此保持高度警惕。任何破坏奥运、抵毁中国的罪恶行径最终将以失败收场。胜利一定属于中国人民。 Mitbbs.com

Decrease font Decrease font
Enlarge font Enlarge font

UNITED NATIONS (AP) -- Two natural disasters in tightly-controlled Asian nations this month have produced two very different responses: Myanmar's very slow reaction to Cyclone Nargis, and China's speedy response to a killer earthquake. 

Protesters in Hong Kong demonstrate against the Myanmar military junta's response to the recent cyclone.

Myanmar's sparked international outrage. China's won admiration.

Britain's U.N. Ambassador John Sawers also said the two disaster responses were different.

"I think China has reacted very promptly to the appalling disaster ... and I think the political attention, the rapid response, has been admirable," he said.

- 作者: oいばらの泪o 2008年05月19日, 星期一 23:54  回复(1) |  引用(0) 加入博采

Ogre 3D引擎 笔记~2:键盘&鼠标响应

最近看2D又看不下去了,继续看Ogre解闷。事隔一年了,真快。可惜3D功力还没见长>_<翻了下旧帐,发现自己去年写得东西竟然有点看不懂了,暴汗,赶紧拾起来看看。

刚觉得程序真是一件令人郁闷的东西,语言和语言之间的经验是没有办法共享的,会了一个,另一个语言能做的东西这个却做不了。放眼望去竟是不会的东西。超有挫折感。不过后来翻了翻原先的代码,或者别人的教程,倒是发觉理解能力变强了,代码看看就知道和学过的东西哪些是共通的,哪些是特殊的。嘿嘿,没白写那些代码。

开始看Ogre的键盘&鼠标,之前很晕的东西,现在发现其实还好啦(也可能和英语逐渐能一目十行有关-_-)

Ogre有Buffer Input和Unbuffer Input两种,其实这两种Wiki上的教程都过时了,新的Ogre,OIS已经遭淘汰了,所以Wiki的代码是调不通的。

现在想想FrameListener无非就如同MFC的OnTimer,数据变化的处理都在之中进行。

Buffer Input 是在发生输入响应事件的时候进行,而UnBuffer Input则是在FrameListener里进行。就如同Buffer Input是响应WM_MOUSEMOVE,WM_KEYDOWN一样,而Unbuffer Input则是在OnTimer里检测是否有键盘等事件。

具体的(以下现在都没有了,说说思想吧):

ExampleFrameListener有成员变量mMouse和mKeyboard。

UnBuffer Input在FrameListener里调用mMouse->Catch(),或mKeyboard->Catch()来检测消息。然后if来处理。

Buffer Input是要继承OIS::MouseListener和OIS::KeyListener,这两个类有纯虚函数KeyPressed()和KeyReleased()遗迹MousePressed()和MouseListener()。有处理内容的话,就重载这些纯虚函数就可以了。

目前的做法是要用到CEGUI,所以Wiki的Basic Tutorial 5和6是不用看地。

-------------------------------------------------------------

- 作者: oいばらの泪o 2008年05月18日, 星期日 12:20  回复(0) |  引用(0) 加入博采

游戏外挂之:原理与实践(详)
一、 前言 

  所谓游戏外挂,其实是一种游戏外辅程序,它可以协助玩家自动产生游戏动作、修改游戏网络数据包以及修改游戏内存数据等, 以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然,现在对游戏外挂程序的“合法”身份众说纷纭,在这里我不想对此发表任何个人意见,让时间去 说明一切吧。

  不管游戏外挂程序是不是“合法”身份,但是它却是具有一定的技术含量的,在这
些小小程序中使用了许多高端技术,如拦截Sock技术、拦截API技术、模拟键盘与鼠标技术、直接修改程序内存技术等等。本文将对常见的游戏外挂中使用的技术进行全面剖析。

  二、认识外挂

  游戏外挂的历史可以追溯到单机版游戏时代,只不过当时它使用了另一个更通俗易
懂的名字??游戏修改器。它可以在游戏中追踪锁定游戏主人公的各项能力数值。这样玩家在游戏中可以达到主角不掉血、不耗费魔法、不消耗金钱等目的。这样降低了游戏的难度,使得玩家更容易通关。

  随着网络游戏的时代的来临,游戏外挂在原有的功能之上进行了新的发展,它变得
更加多种多样,功能更加强大,操作更加简单,以至有些游戏的外挂已经成为一个体系,比如《石器时代》,外挂品种达到了几十种,自动战斗、自动行走、自动练级、自动补血、加速、不遇敌、原地遇敌、快速增加经验值、按键精灵……几乎无所不包。

  游戏外挂的设计主要是针对于某个游戏开发的,我们可以根据它针对的游戏的类型
可大致可将外挂分为两种大类。

  一类是将游戏中大量繁琐和无聊的攻击动作使用外挂自动完成,以帮助玩家轻松搞
定 攻击对象并可以快速的增加玩家的经验值。比如在《龙族》中有一种工作的设定,玩家的工作等级越高,就可以驾驭越好的装备。但是增加工作等级却不是一件有趣 的事情,毋宁说是重复枯燥的机械劳动。如果你想做法师用的杖,首先需要做基本工作--?砍树。砍树的方法很简单,在一棵大树前不停的点鼠标就可以了,每 10000的经验升一级。这就意味着玩家要在大树前不停的点击鼠标,这种无聊的事情通过"按键精灵"就可以解决。外挂的"按键精灵"功能可以让玩家摆脱无 趣的点击鼠标的工作。

  另一类是由外挂程序产生欺骗性的网络游戏封包,并将这些封包发送到网络游戏服务器,利用这些虚假信息欺骗服务器进行游戏数值的修改,达到修改角色能力数值的目的。这类外挂程序针对性很
强,一般在设计时都是针对某个游戏某个版本来做的,因为每个网络游戏服务器与客户端交流的数据包各不相同,外挂程序必须要对欺骗的网络游戏服务器的数据包进行分析,才能产生服务器识别的数据包。这类外挂程序也是当前最流利的一类游戏外挂程序。

  另外,现在很多外挂程序功能强大,不仅实现了自动动作代理和封包功能,而且还
提供了对网络游戏的客户端程序的数据进行修改,以达到欺骗网络游戏服务器的目的。我相信,随着网络游戏商家的反外挂技术的进展,游戏外挂将会产生更多更优秀的技术,让我们期待着看场技术大战吧......

  三、外挂技术综述

  可以将开发游戏外挂程序的过程大体上划分为两个部分:

  前期部分工作是对外挂的主体游戏进行分析,不同类型的外挂分析主体游戏的内容也不相同。如外挂为上述谈到的外挂类型中的第一类时,其分析过程常是针对游戏的场景中的攻击对象的位置和分布
情 况进行分析,以实现外挂自动进行攻击以及位置移动。如外挂为外挂类型中的第二类时,其分析过程常是针对游戏服务器与客户端之间通讯包数据的结构、内容以及 加密算法的分析。因网络游戏公司一般都不会公布其游戏产品的通讯包数据的结构、内容和加密算法的信息,所以对于开发第二类外挂成功的关键在于是否能正确分 析游戏包数据的结构、内容以及加密算法,虽然可以使用一些工具辅助分析,但是这还是一种坚苦而复杂的工作。

  后期部分工作主要是根据前期对游戏的分析结果,使用大量的程序开发技术编写外
挂 程序以实现对游戏的控制或修改。如外挂程序为第一类外挂时,通常会使用到鼠标模拟技术来实现游戏角色的自动位置移动,使用键盘模拟技术来实现游戏角色的自 动攻击。如外挂程序为第二类外挂时,通常会使用到挡截Sock和挡截API函数技术,以挡截游戏服务器传来的网络数据包并将数据包修改后封包后传给游戏服 务器。另外,还有许多外挂使用对游戏客户端程序内存数据修改技术以及游戏加速技术。

  本文主要是针对开发游戏外挂程序后期使用的程序开发技术进行探讨,重点介绍的
如下几种在游戏外挂中常使用的程序开发技术:

  ● 动作模拟技术:主要包括键盘模拟技术和鼠标模拟技术。

  ● 封包技术:主要包括挡截Sock技术和挡截API技术。 
 
四、动作模拟技术   

我们在前面介绍过,几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加玩家的功力,还有那些数不完的迷宫,这些好 像已经成为了角色游戏的代名词。现在,外挂可以帮助玩家从这些繁琐而无聊的工作中摆脱出来,专注于游戏情节的进展。外挂程序为了实现自动角色位置移动和自 动攻击等功能,需要使用到键盘模拟技术和鼠标模拟技术。

下面我们将重点介绍这些技术并编写一个简单的实例帮助读者理解动作模拟技术的实现过程。

  1. 鼠标模拟技术
  
  几乎所有的游戏中都使用了鼠标来改变角色的位置和方向,玩家仅用一个小小的鼠标,就可以使角色畅游天下。

那么,我们如何实现在没有玩家的参与下角色也可以自动行走呢。其实实现这个并不难,仅仅几个Windows API函数就可以搞定,让我们先来认识认识这些API函数。

  (1) 模拟鼠标动作API函数mouse_event,它可以实现模拟鼠标按下和放开等动作。

    VOID mouse_event(
      DWORD dwFlags, // 鼠标动作标识。
      DWORD dx, // 鼠标水平方向位置。
      DWORD dy, // 鼠标垂直方向位置。
      DWORD dwData, // 鼠标轮子转动的数量。
      DWORD dwExtraInfo // 一个关联鼠标动作辅加信息。
    );

  其中,dwFlags表示了各种各样的鼠标动作和点击活动,它的常用取值如下:

   MOUSEEVENTF_MOVE 表示模拟鼠标移动事件。

   MOUSEEVENTF_LEFTDOWN 表示模拟按下鼠标左键。

   MOUSEEVENTF_LEFTUP 表示模拟放开鼠标左键。

   MOUSEEVENTF_RIGHTDOWN 表示模拟按下鼠标右键。

   MOUSEEVENTF_RIGHTUP 表示模拟放开鼠标右键。

   MOUSEEVENTF_MIDDLEDOWN 表示模拟按下鼠标中键。

   MOUSEEVENTF_MIDDLEUP 表示模拟放开鼠标中键。

  (2)、设置和获取当前鼠标位置的API函数。获取当前鼠标位置使用GetCursorPos()函数,设置当前鼠标位置使用

SetCursorPos()函数。

    BOOL GetCursorPos(
     LPPOINT lpPoint // 返回鼠标的当前位置。
    );
    BOOL SetCursorPos(
    int X, // 鼠标的水平方向位置。
      int Y //鼠标的垂直方向位置。
    );

  通常游戏角色的行走都是通过鼠标移动至目的地,然后按一下鼠标的按钮就搞定了。下面我们使用上面介绍的API

函数来模拟角色行走过程。

   CPoint oldPoint,newPoint;
   GetCursorPos(&oldPoint); //保存当前鼠标位置。
   newPoint.x = oldPoint.x+40;
   newPoint.y = oldPoint.y+10;
   SetCursorPos(newPoint.x,newPoint.y); //设置目的地位置。
   mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);//模拟按下鼠标右键。
   mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);//模拟放开鼠标右键。

  2. 键盘模拟技术

  在很多游戏中,不仅提供了鼠标的操作,而且还提供了键盘的操作,在对攻击对象进行攻击时还可以使用快捷键。为了使这些攻击过程能够自动进行,外挂程序需要使用键盘模拟技术。像鼠标模拟技术一样,Windows API也提供了一系列API函数来完成对键盘动作的模拟。

  模拟键盘动作API函数keydb_event,它可以模拟对键盘上的某个或某些键进行按下或放开的动作。

   VOID keybd_event(
     BYTE bVk, // 虚拟键值。
     BYTE bScan, // 硬件扫描码。
     DWORD dwFlags, // 动作标识。
     DWORD dwExtraInfo // 与键盘动作关联的辅加信息。
   );

   其中,bVk表示虚拟键值,其实它是一个BYTE类型值的宏,其取值范围为1-254。有关虚拟键值表请在MSDN上使用关键字“Virtual- Key Codes”查找相关资料。bScan表示当键盘上某键被按下和放开时,键盘系统硬件产生的扫描码,我们可以MapVirtualKey()函数 在虚拟键值与扫描码之间进行转换。dwFlags表示各种各样的键盘动作,它有两种取值:KEYEVENTF_EXTENDEDKEY和 KEYEVENTF_KEYUP。

  下面我们使用一段代码实现在游戏中按下Shift+R快捷键对攻击对象进行攻击。

   keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按下CTRL键。
   keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//键下R键。
   keybd_event(0x52,MapVirtualKey(0x52,0), KEYEVENTF_KEYUP,0);//放开R键。
   keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),
   KEYEVENTF_KEYUP,0);//放开CTRL键。

  3. 激活外挂

  上面介绍的鼠标和键盘模拟技术实现了对游戏角色的动作部分的模拟,但要想外挂能工作于游戏之上,还需要将其与游戏的场景窗口联系起来或者使用一个激活键,就象按键精灵的那个激活键一样。
我们可以用GetWindow函数来枚举窗口,也可以用Findwindow函数来查找特定的窗口。另外还有一个FindWindowEx函数
可以找到窗口的子窗口,当游戏切换场景的时候我们可以用FindWindowEx来确定一些当前窗口的特征,从而判断是否
还在这个场景,方法很多了,比如可以GetWindowInfo来确定一些东西,比如当查找不到某个按钮的时候就说明游戏
场景已经切换了等等办法。当使用激活键进行关联,需要使用Hook技术开发一个全局键盘钩子,在这里就不具体介绍全
局钩子的开发过程了,在后面的实例中我们将会使用到全局钩子,到时将学习到全局钩子的相关知识。

4. 实例实现

  通过上面的学习,我们已经基本具备了编写动作式游戏外挂的能力了。下面我们将创建一个画笔程序外挂,它实

现自动移动画笔字光标的位置并写下一个红色的“R”字。以这个实例为基础,加入相应的游戏动作规则,就可以实现

一个完整的游戏外挂。这里作者不想使用某个游戏作为例子来开发外挂(因没有游戏商家的授权啊!),如读者感兴

趣的话可以找一个游戏试试,最好仅做测试技术用。

  首先,我们需要编写一个全局钩子,使用它来激活外挂,激活键为F10。创建全局钩子步骤如下:

  (1).选择MFC AppWizard(DLL)创建项目ActiveKey,并选择MFC Extension DLL
(共享MFC拷贝)类型。

  (2).插入新文件ActiveKey.h,在其中输入如下代码:

   #ifndef _KEYDLL_H
   #define _KEYDLL_H

   class AFX_EXT_CLASS CKeyHook:public CObject
   {
    public:
 CKeyHook();
 ~CKeyHook();
 HHOOK Start(); //安装钩子
 BOOL Stop(); //卸载钩子
   };
   #endif

  (3).在ActiveKey.cpp文件中加入声明"#include ActiveKey.h"。

  (4).在ActiveKey.cpp文件中加入共享数据段,代码如下:

   //Shared data section
   #pragma data_seg("sharedata")
   HHOOK glhHook=NULL; //钩子句柄。
   HINSTANCE glhInstance=NULL; //DLL实例句柄。
   #pragma data_seg()

  (5).在ActiveKey.def文件中设置共享数据段属性,代码如下:

   SETCTIONS
   shareddata READ WRITE SHARED

  (6).在ActiveKey.cpp文件中加入CkeyHook类的实现代码和钩子函数代码:

   //键盘钩子处理函数。
   extern "C" LRESULT WINAPI KeyboardProc(int nCode,WPARAM wParam,LPARAM
lParam)
   {
   if( nCode >= 0 )
   {
   if( wParam == 0X79 )//当按下F10键时,激活外挂。
 {
  //外挂实现代码。
CPoint newPoint,oldPoint;
   GetCursorPos(&oldPoint);
   newPoint.x = oldPoint.x+40;
   newPoint.y = oldPoint.y+10;
   SetCursorPos(newPoint.x,newPoint.y);
   mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模拟按下鼠标左键。
  mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模拟放开鼠标左键。
  keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0); //按下SHIFT键。
  keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R键。
  keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放开R键。
  keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放开
SHIFT键。
      SetCursorPos(oldPoint.x,oldPoint.y);
 }
   }
   return CallNextHookEx(glhHook,nCode,wParam,lParam);
   }

   CKeyHook::CKeyHook(){}
   CKeyHook::~CKeyHook()
   { 
   if( glhHook )
Stop();
   }
   //安装全局钩子。
   HHOOK CKeyHook::Start()
   {
glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//设置键盘钩子。
return glhHook;
}
   //卸载全局钩子。
   BOOL CKeyHook::Stop()
   {
   BOOL bResult = TRUE;
 if( glhHook )
   bResult = UnhookWindowsHookEx(glhHook);//卸载键盘钩子。
   return bResult;
   }

  (7).修改DllMain函数,代码如下:

   extern "C" int APIENTRY
   DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
   {
//如果使用lpReserved参数则删除下面这行
UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)
{
  TRACE0("NOtePadHOOK.DLL Initializing!\n");
   //扩展DLL仅初始化一次
  if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))
return 0;
  new CDynLinkLibrary(ActiveKeyDLL);
      //把DLL加入动态MFC类库中
  glhInstance = hInstance;
  //插入保存DLL实例句柄
}
else if (dwReason == DLL_PROCESS_DETACH)
{
  TRACE0("NotePadHOOK.DLL Terminating!\n");
  //终止这个链接库前调用它
  AfxTermExtensionModule(ActiveKeyDLL);
}
return 1;
   }

  (8).编译项目ActiveKey,生成ActiveKey.DLL和ActiveKey.lib。

  接着,我们还需要创建一个外壳程序将全局钩子安装了Windows系统中,这个外壳序编写步骤如下:

  (1).创建一个对话框模式的应用程序,项目名为Simulate。

  (2).在主对话框中加入一个按钮,使用ClassWizard为其创建CLICK事件。

  (3).将ActiveKey项目Debug目录下的ActiveKey.DLL和ActiveKey.lib拷贝到Simulate项目目录下。

  (4).从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标签,在“对象/库模块”中输入

ActiveKey.lib。

(5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,并在
Stdafx.h中加入#include 

ActiveKey.h。

  (6).在按钮单击事件函数输入如下代码:

   void CSimulateDlg::OnButton1()
   {
// TODO: Add your control notification handler code here
if( !bSetup )
{
m_hook.Start();//激活全局钩子。
}
else
{
m_hook.Stop();//撤消全局钩子。
}
bSetup = !bSetup;

   }

  (7).编译项目,并运行程序,单击按钮激活外挂。

  (8).启动画笔程序,选择文本工具并将笔的颜色设置为红色,将鼠标放在任意位置后,按F10键,画笔程序自动移

动鼠标并写下一个红色的大写R。图一展示了按F10键前的画笔程序的状态,图二展示了按F10键后的画笔程序的状态。


图一:按F10前状态(001.jpg)


图二:按F10后状态(002.jpg)


五、封包技术

  通过对动作模拟技术的介绍,我们对游戏外挂有了一定程度上的认识,也学会了使用动作模拟技术来实现简单的

动作模拟型游戏外挂的制作。这种动作模拟型游戏外挂有一定的局限性,它仅仅只能解决使用计算机代替人力完成那

么有规律、繁琐而无聊的游戏动作。但是,随着网络游戏的盛行和复杂度的增加,很多游戏要求将客户端动作信息及

时反馈回服务器,通过服务器对这些动作信息进行有效认证后,再向客户端发送下一步游戏动作信息,这样动作模拟

技术将失去原有的效应。为了更好地“外挂”这些游戏,游戏外挂程序也进行了升级换代,它们将以前针对游戏用户

界面层的模拟推进到数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏控制数据包,分析数据包并修

改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务,这个过程其实就是一个封包

的过程。

  封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,实现方法也很多,如挡截

WinSock、挡截API函数、挡截消息、VxD驱动程序等。在此我们也不可能在此文中将所有的封包技术都进行详细介绍,

故选择两种在游戏外挂程序中最常用的两种方法:挡截WinSock和挡截API函数。

  1. 挡截WinSock

  众所周知,Winsock是Windows网络编程接口,它工作于Windows应用层,它提供与底层传输协议无关的高层数据传

输编程接口。在Windows系统中,使用WinSock接口为应用程序提供基于TCP/IP协议的网络访问服务,这些服务是由

Wsock32.DLL动态链接库提供的函数库来完成的。

  由上说明可知,任何Windows基于TCP/IP的应用程序都必须通过WinSock接口访问网络,当然网络游戏程序也不例

外。由此我们可以想象一下,如果我们可以控制WinSock接口的话,那么控制游戏客户端程序与服务器之间的数据包也

将易如反掌。按着这个思路,下面的工作就是如何完成控制WinSock接口了。由上面的绍可知,WinSock接口其实是

由一个动态链接库提供的一系列函数,由这些函数实现对网络的访问。有了这层的认识,问题就好办多了,我们可以

制作一个类似的动态链接库来代替原WinSock接口库,在其中实现WinSock32.dll中实现的所有函数,并保证所有函数

的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中,可以对我们感兴趣的函数(如发送、接

收等函数)进行挡截,放入外挂控制代码,最后还继续调用原WinSock库中提供的相应功能函数,这样就可以实现对网

络数据包的挡截、修改和发送等封包功能。

  下面重点介绍创建挡截WinSock外挂程序的基本步骤:

  (1) 创建DLL项目,选择Win32 Dynamic-Link Library,再选择An empty DLLproject。

  (2) 新建文件wsock32.h,按如下步骤输入代码:

  ① 加入相关变量声明:

   HMODULE hModule=NULL; //模块句柄
   char buffer[1000]; //缓冲区
   FARPROC proc; //函数入口指针

  ② 定义指向原WinSock库中的所有函数地址的指针变量,因WinSock库共提供70多个函数,限于篇幅,在此就只选

择几个常用的函数列出,有关这些库函数的说明可参考MSDN相关内容。

   //定义指向原WinSock库函数地址的指针变量。
   SOCKET (__stdcall *socket1)(int ,int,int);//创建Sock函数。
   int (__stdcall *WSAStartup1)(WORD,LPWSADATA);//初始化WinSock库函数。
   int (__stdcall *WSACleanup1)();//清除WinSock库函数。
   int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );//接收数据函数。
   int (__stdcall *send1)(SOCKET ,const char * ,int ,int);//发送数据函数。
   int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);//创建连接函数。
   int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );//绑定函数。
   ......其它函数地址指针的定义略。

  (3) 新建wsock32.cpp文件,按如下步骤输入代码:

  ① 加入相关头文件声明:

   #include 
   #include 
   #include "wsock32.h"

  ② 添加DllMain函数,在此函数中首先需要加载原WinSock库,并获取此库中所有函数的地址。代码如下:

   BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOIDlpReserved)
   {
    if(hModule==NULL){
     //加载原WinSock库,原WinSock库已复制为wsock32.001。
   hModule=LoadLibrary("wsock32.001");
  }
    else return 1;
//获取原WinSock库中的所有函数的地址并保存,下面仅列出部分代码。
if(hModule!=NULL){
     //获取原WinSock库初始化函数的地址,并保存到WSAStartup1中。
proc=GetProcAddress(hModule,"WSAStartup");
   WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;
     //获取原WinSock库消除函数的地址,并保存到WSACleanup1中。
    proc=GetProcAddress(hModule i,"WSACleanup");
    WSACleanup1=(int (_stdcall *)())proc;
     //获取原创建Sock函数的地址,并保存到socket1中。
    proc=GetProcAddress(hModule,"socket");
     socket1=(SOCKET (_stdcall *)(int ,int,int))proc;
     //获取原创建连接函数的地址,并保存到connect1中。
     proc=GetProcAddress(hModule,"connect");
     connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr*,int ))proc;
     //获取原发送函数的地址,并保存到send1中。
     proc=GetProcAddress(hModule,"send");
     send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;
     //获取原接收函数的地址,并保存到recv1中。
     proc=GetProcAddress(hModule,"recv");
     recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;
     ......其它获取函数地址代码略。
   }
   else return 0;
   return 1;
}

  ③ 定义库输出函数,在此可以对我们感兴趣的函数中添加外挂控制代码,在所有的输出函数的最后一步都调用原

WinSock库的同名函数。部分输出函数定义代码如下:

//库输出函数定义。
//WinSock初始化函数。
    int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA
lpWSAData)
    {
     //调用原WinSock库初始化函数
     return WSAStartup1(wVersionRequired,lpWSAData);
    }
    //WinSock结束清除函数。
    int PASCAL FAR WSACleanup(void)
    {
     return WSACleanup1(); //调用原WinSock库结束清除函数。
    }
    //创建Socket函数。
    SOCKET PASCAL FAR socket (int af, int type, int protocol)
    {
     //调用原WinSock库创建Socket函数。
     return socket1(af,type,protocol);
    }
    //发送数据包函数
    int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)
    {
   //在此可以对发送的缓冲buf的内容进行修改,以实现欺骗服务器。
   外挂代码......
   //调用原WinSock库发送数据包函数。
     return send1(s,buf,len,flags);
    }
//接收数据包函数。
    int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
    {
   //在此可以挡截到服务器端发送到客户端的数据包,先将其保存到buffer中。
   strcpy(buffer,buf);
   //对buffer数据包数据进行分析后,对其按照玩家的指令进行相关修改。
   外挂代码......
   //最后调用原WinSock中的接收数据包函数。
     return recv1(s, buffer, len, flags);
     }
    .......其它函数定义代码略。

  (4)、新建wsock32.def配置文件,在其中加入所有库输出函数的声明,部分声明代码如下:

   LIBRARY "wsock32"
   EXPORTS
    WSAStartup @1
   WSACleanup @2
    recv @3
    send @4
    socket @5
   bind @6
   closesocket @7
   connect @8
        ......其它输出函数声明代码略

       (5)、从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标签,在“对象/库模块”中输入 

Ws2_32.lib。

  (6)、编译项目,产生wsock32.dll库文件。

  (7)、将系统目录下原wsock32.dll库文件拷贝到被外挂程序的目录下,并将其改名为wsock.001;再将上面产生的

wsock32.dll文件同样拷贝到被外挂程序的目录下。重新启动游戏程序,此时游戏程序将先加载我们自己制作的

wsock32.dll文件,再通过该库文件间接调用原WinSock接口函数来实现访问网络。上面我们仅仅介绍了挡载WinSock的

实现过程,至于如何加入外挂控制代码,还需要外挂开发人员对游戏数据包结构、内容、加密算法等方面的仔细分析

(这个过程将是一个艰辛的过程),再生成外挂控制代码。关于数据包分析方法和技巧,不是本文讲解的范围,如您

感兴趣可以到网上查查相关资料。

2.挡截API

  挡截API技术与挡截WinSock技术在原理上很相似,但是前者比后者提供了更强大的
功能。挡截WinSock仅只能挡截

WinSock接口函数,而挡截API可以实现对应用程序调用的包括WinSock API函数在内的
所有API函数的挡截。如果您的

外挂程序仅打算对WinSock的函数进行挡截的话,您可以只选择使用上小节介绍的挡截
WinSock技术。随着大量外挂程

序在功能上的扩展,它们不仅仅只提供对数据包的挡截,而且还对游戏程序中使用的
Windows API或其它DLL库函数的

挡截,以使外挂的功能更加强大。例如,可以通过挡截相关API函数以实现对非中文游
戏的汉化功能,有了这个利器,

可以使您的外挂程序无所不能了。

  挡截API技术的原理核心也是使用我们自己的函数来替换掉Windows或其它DLL库提
供的函数,有点同挡截WinSock

原理相似吧。但是,其实现过程却比挡截WinSock要复杂的多,如像实现挡截Winsock过
程一样,将应用程序调用的所

有的库文件都写一个模拟库有点不大可能,就只说Windows API就有上千个,还有很多
库提供的函数结构并未公开,所

以写一个模拟库代替的方式不大现实,故我们必须另谋良方。

  挡截API的最终目标是使用自定义的函数代替原函数。那么,我们首先应该知道应
用程序何时、何地、用何种方式

调用原函数。接下来,需要将应用程序中调用该原函数的指令代码进行修改,使它将调
用函数的指针指向我们自己定

义的函数地址。这样,外挂程序才能完全控制应用程序调用的API函数,至于在其中如
何加入外挂代码,就应需求而异

了。最后还有一个重要的问题要解决,如何将我们自定义的用来代替原API函数的函数
代码注入被外挂游戏程序进行地

址空间中,因在Windows系统中应用程序仅只能访问到本进程地址空间内的代码和数
据。

  综上所述,要实现挡截API函数,至少需要解决如下三个问题:

  ● 如何定位游戏程序中调用API函数指令代码?

  ● 如何修改游戏程序中调用API函数指令代码?

  ● 如何将外挂代码(自定义的替换函数代码)注入到游戏程序进程地址空间?

  下面我们逐一介绍这几个问题的解决方法:

  (1) 、定位调用API函数指令代码

  我们知道,在汇编语言中使用CALL指令来调用函数或过程的,它是通过指令参数中
的函数地址而定位到相应的函

数代码的。那么,我们如果能寻找到程序代码中所有调用被挡截的API函数的CALL指令
的话,就可以将该指令中的函数

地址参数修改为替代函数的地址。虽然这是一个可行的方案,但是实现起来会很繁琐,
也不稳健。庆幸的是,Windows

系统中所使用的可执行文件(PE格式)采用了输入地址表机制,将所有在程序调用的
API函数的地址信息存放在输入地

址表中,而在程序代码CALL指令中使用的地址不是API函数的地址,而是输入地址表中
该API函数的地址项,如想使程

序代码中调用的API函数被代替掉,只用将输入地址表中该API函数的地址项内容修改即
可。具体理解输入地址表运行

机制,还需要了解一下PE格式文件结构,其中图三列出了PE格式文件的大致结构。


  图三:PE格式大致结构图(003.jpg)

  PE格式文件一开始是一段DOS程序,当你的程序在不支持Windows的环境中运行时,
它就会显示“This Program

cannot be run in DOS mode”这样的警告语句,接着这个DOS文件头,就开始真正的PE
文件内容了。首先是一段称为

“IMAGE_NT_HEADER”的数据,其中是许多关于整个PE文件的消息,在这段数据的尾端
是一个称为Data Directory的数

据表,通过它能快速定位一些PE文件中段(section)的地址。在这段数据之后,则是
一个“IMAGE_SECTION_HEADER”

的列表,其中的每一项都详细描述了后面一个段的相关信息。接着它就是PE文件中最主
要的段数据了,执行代码、数

据和资源等等信息就分别存放在这些段中。

  在所有的这些段里,有一个被称为“.idata”的段(输入数据段)值得我们去注
意,该段中包含着一些被称为输

入地址表(IAT,Import Address Table)的数据列表。每个用隐式方式加载的API所在
的DLL都有一个IAT与之对应,

同时一个API的地址也与IAT中一项相对应。当一个应用程序加载到内存中后,针对每一
个API函数调用,相应的产生如

下的汇编指令:

  JMP DWORD PTR [XXXXXXXX]

  或

  CALL DWORD PTR [XXXXXXXX]

  其中,[XXXXXXXX]表示指向了输入地址表中一个项,其内容是一个DWORD,而正是
这个DWORD才是API函数在内存中

的真正地址。因此我们要想拦截一个API的调用,只要简单的把那个DWORD改为我们自己
的函数的地址。

  (2) 、修改调用API函数代码

  从上面对PE文件格式的分析可知,修改调用API函数代码其实是修改被调用API函数
在输入地址表中IAT项内容。由

于Windows系统对应用程序指令代码地址空间的严密保护机制,使得修改程序指令代码
非常困难,以至于许多高手为之

编写VxD进入Ring0。在这里,我为大家介绍一种较为方便的方法修改进程内存,它仅需
要调用几个Windows核心API函

数,下面我首先来学会一下这几个API函数:

   DWORD VirtualQuery(
   LPCVOID lpAddress, // address of region
   PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer
   DWORD dwLength // size of buffer
   );

  该函数用于查询关于本进程内虚拟地址页的信息。其中,lpAddress表示被查询页
的区域地址;lpBuffer表示用于

保存查询页信息的缓冲;dwLength表示缓冲区大小。返回值为实际缓冲大小。

   BOOL VirtualProtect(
   LPVOID lpAddress, // region of committed pages
   SIZE_T dwSize, // size of the region
   DWORD flNewProtect, // desired access protection
   PDWORD lpflOldProtect // old protection
   );

  该函数用于改变本进程内虚拟地址页的保护属性。其中,lpAddress表示被改变保
护属性页区域地址;dwSize表示

页区域大小;flNewProtect表示新的保护属性,可取值为PAGE_READONLY、
PAGE_READWRITE、PAGE_EXECUTE等;

lpflOldProtect表示用于保存改变前的保护属性。如果函数调用成功返回“T”,否则
返回“F”。

  有了这两个API函数,我们就可以随心所欲的修改进程内存了。首先,调用
VirtualQuery()函数查询被修改内存的

页信息,再根据此信息调用VirtualProtect()函数改变这些页的保护属性为
PAGE_READWRITE,有了这个权限您就可以

任意修改进程内存数据了。下面一段代码演示了如何将进程虚拟地址为0x0040106c处的
字节清零。

   BYTE* pData = 0x0040106c;
   MEMORY_BASIC_INFORMATION mbi_thunk;
   //查询页信息。
   VirtualQuery(pData, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
   //改变页保护属性为读写。
   VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
   PAGE_READWRITE, &mbi_thunk.Protect);
   //清零。
   *pData = 0x00;
   //恢复页的原保护属性。
   DWORD dwOldProtect;
   VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
   mbi_thunk.Protect, &dwOldProtect);
(3)、注入外挂代码进入被挂游戏进程中

  完成了定位和修改程序中调用API函数代码后,我们就可以随意设计自定义的API函
数的替代函数了。做完这一切

后,还需要将这些代码注入到被外挂游戏程序进程内存空间中,不然游戏进程根本不会
访问到替代函数代码。注入方

法有很多,如利用全局钩子注入、利用注册表注入挡截User32库中的API函数、利用
CreateRemoteThread注入(仅限于

NT/2000)、利用BHO注入等。因为我们在动作模拟技术一节已经接触过全局钩子,我相
信聪明的读者已经完全掌握了

全局钩子的制作过程,所以我们在后面的实例中,将继续利用这个全局钩子。至于其它
几种注入方法,如果感兴趣可

参阅MSDN有关内容。

  有了以上理论基础,我们下面就开始制作一个挡截MessageBoxA和recv函数的实
例,在开发游戏外挂程序 时,可

以此实例为框架,加入相应的替代函数和处理代码即可。此实例的开发过程如下:

  (1) 打开前面创建的ActiveKey项目。

  (2) 在ActiveKey.h文件中加入HOOKAPI结构,此结构用来存储被挡截API函数名
称、原API函数地址和替代函数地

址。

   typedef struct tag_HOOKAPI
   {
   LPCSTR szFunc;//被HOOK的API函数名称。
   PROC pNewProc;//替代函数地址。
   PROC pOldProc;//原API函数地址。
   }HOOKAPI, *LPHOOKAPI;

  (3) 打开ActiveKey.cpp文件,首先加入一个函数,用于定位输入库在输入数据段
中的IAT地址。代码如下:

   extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR
   LocationIAT(HMODULE hModule, LPCSTR szImportMod)
   //其中,hModule为进程模块句柄;szImportMod为输入库名称。
   {
   //检查是否为DOS程序,如是返回NULL,因DOS程序没有IAT。
   PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
   if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
    //检查是否为NT标志,否则返回NULL。
    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+
(DWORD)(pDOSHeader-

>e_lfanew));
    if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;
    //没有IAT表则返回NULL。
    
if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Vir
tualAddress == 0)

return NULL;
    //定位第一个IAT位置。
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)

(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Virtu
alAddress));
    //根据输入库名称循环检查所有的IAT,如匹配则返回该IAT地址,否则检测下
一个IAT。
    while (pImportDesc->Name)
    {
     //获取该IAT描述的输入库名称。
   PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader +
(DWORD)(pImportDesc->Name));
   if (stricmp(szCurrMod, szImportMod) == 0) break;
   pImportDesc++;
    }
    if(pImportDesc->Name == NULL) return NULL;
   return pImportDesc;
   }

  再加入一个函数,用来定位被挡截API函数的IAT项并修改其内容为替代函数地址。
代码如下:

   extern "C" __declspec(dllexport)
   HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI
pHookApi)
   //其中,hModule为进程模块句柄;szImportMod为输入库名称;pHookAPI为
HOOKAPI结构指针。
   {
    //定位szImportMod输入库在输入数据段中的IAT地址。
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule,
szImportMod);
  if (pImportDesc == NULL) return FALSE;
    //第一个Thunk地址。
    PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule +
(DWORD)(pImportDesc-

>OriginalFirstThunk));
   //第一个IAT项的Thunk地址。
    PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule +
(DWORD)(pImportDesc-

>FirstThunk));
    //循环查找被截API函数的IAT项,并使用替代函数地址修改其值。
   while(pOrigThunk->u1.Function)
{
 //检测此Thunk是否为IAT项。
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
  //获取此IAT项所描述的函数名称。
 PIMAGE_IMPORT_BY_NAME pByName
=(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk-

>u1.AddressOfData));
 if(pByName->Name[0] == \0) return FALSE;
  //检测是否为挡截函数。
if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0)
  {
       MEMORY_BASIC_INFORMATION mbi_thunk;
       //查询修改页的信息。
       VirtualQuery(pRealThunk, &mbi_thunk,
sizeof(MEMORY_BASIC_INFORMATION));
//改变修改页保护属性为PAGE_READWRITE。
       VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
PAGE_READWRITE,

&mbi_thunk.Protect);
//保存原来的API函数地址。
      if(pHookApi->pOldProc == NULL)
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function;
  //修改API函数IAT项内容为替代函数地址。
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc;
//恢复修改页保护属性。
DWORD dwOldProtect;
       VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
mbi_thunk.Protect,

&dwOldProtect);
      }
}
  pOrigThunk++;
  pRealThunk++;
}
  SetLastError(ERROR_SUCCESS); //设置错误为ERROR_SUCCESS,表示成功。
  return TRUE;
   }

  (4) 定义替代函数,此实例中只给MessageBoxA和recv两个API进行挡截。代码如下

   static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR
lpCaption, UINT uType)
   {
    //过滤掉原MessageBoxA的正文和标题内容,只显示如下内容。
return MessageBox(hWnd, "Hook API OK!", "Hook API", uType);
   }
   static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )
   {
   //此处可以挡截游戏服务器发送来的网络数据包,可以加入分析和处理数据代
码。
   return recv(s,buf,len,flags);
   }

  (5) 在KeyboardProc函数中加入激活挡截API代码,在if( wParam == 0X79 )语句
中后面加入如下else if语句:

   ......
   //当激活F11键时,启动挡截API函数功能。
   else if( wParam == 0x7A )
   {
    HOOKAPI api[2];
api[0].szFunc ="MessageBoxA";//设置被挡截函数的名称。
api[0].pNewProc = (PROC)MessageBoxA1;//设置替代函数的地址。
api[1].szFunc ="recv";//设置被挡截函数的名称。
api[1].pNewProc = (PROC)recv1; //设置替代函数的地址。
//设置挡截User32.dll库中的MessageBoxA函数。
HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);
//设置挡截Wsock32.dll库中的recv函数。
HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&api[1]);
   }
   ......



    (6) 在ActiveKey.cpp中加入头文件声明 "#include "wsock32.h"。 从“工程”菜单中选择“设置”,弹出 

Project Setting对话框,选择Link标签,在“对象/库模块”中输入Ws2_32..lib。

  (7) 重新编译ActiveKey项目,产生ActiveKey.dll文件,将其拷贝到Simulate.exe目录下。运行Simulate.exe并

启动全局钩子。激活任意应用程序,按F11键后,运行此程序中可能调用MessageBoxA函数的操作,看看信息框是不是

有所变化。同样,如此程序正在接收网络数据包,就可以实现封包功能了。

  六、结束语

  除了以上介绍的几种游戏外挂程序常用的技术以外,在一些外挂程序中还使用了游
戏数据修改技术、游戏加速技术等。在这篇文章里,就不逐一介绍了。

- 作者: oいばらの泪o 2008年05月17日, 星期六 08:34  回复(0) |  引用(0) 加入博采

游戏外挂之:原理与实践
 1、游戏外挂的原理

  外挂现在分为好多种,比如模拟键盘的,鼠标的,修改数据包的,还有修改本地内存的,但好像没有修改服务器内存

的哦,呵呵。其实修改服务器也是有办法的,只是技术太高一般人没有办法入手而已。(比如请GM去夜总会、送礼、收黑

钱等等办法都可以修改服务器数据,哈哈)

  修改游戏无非是修改一下本地内存的数据,或者截获API函数等等。这里我把所能想到的方法都作一个介绍,希望大

家能做出很好的外挂来使游戏厂商更好的完善自己的技术。我见到一篇文章是讲魔力宝贝的理论分析,写得不错,大概是

那个样子。下来我就讲解一下技术方面的东西,以作引玉之用。

  2 技术分析部分

  2.1 模拟键盘或鼠标的响应

  我们一般使用:

  UINT SendInput(
    UINT nInputs,   // count of input events
    PINPUT pInputs, // array of input events
    int cbSize    // size of structure
  );  

  API函数。第一个参数是说明第二个参数的矩阵的维数的,第二个参数包含了响应事件,这个自己填充就可以,最后

是这个结构的大小,非常简单,这是最简单的方法模拟键盘鼠标了,呵呵。注意,这个函数还有个替代函数:

  VOID keybd_event(
    BYTE bVk,       // 虚拟键码
    BYTE bScan,      // 扫描码
    DWORD dwFlags,
    ULONG_PTR dwExtraInfo // 附加键状态
  );  

  与

  VOID mouse_event(
    DWORD dwFlags,      // motion and click options
    DWORD dx,         // horizontal position or change
    DWORD dy,        // vertical position or change
    DWORD dwData,      // wheel movement
    ULONG_PTR dwExtraInfo  // application-defined information
  );  

  这两个函数非常简单了,我想那些按键精灵就是用的这个吧。上面的是模拟键盘,下面的是模拟鼠标的。这个仅仅是

模拟部分,要和游戏联系起来我们还需要找到游戏的窗口才行,或者包含快捷键,就象按键精灵的那个激活键一样,我们

可以用GetWindow函数来枚举窗口,也可以用Findwindow函数来查找制定的窗口(注意,还有一个FindWindowEx),

FindwindowEx可以找到窗口的子窗口,比如按钮,等什么东西。当游戏切换场景的时候我们可以用FindWindowEx来确定一

些当前窗口的特征,从而判断是否还在这个场景,方法很多了,比如可以GetWindowInfo来确定一些东西,比如当查找不

到某个按钮的时候就说明游戏场景已经切换了,等等办法。有的游戏没有控件在里面,这是对图像做坐标变换的话,这种

方法就要受到限制了。这就需要我们用别的办法来辅助分析了。

  至于快捷键我们要用动态连接库实现了,里面要用到hook技术了,这个也非常简单。大家可能都会了,其实就是一个

全局的hook对象然后SetWindowHook就可以了,回调函数都是现成的,而且现在网上的例子多如牛毛。这个实现在外挂中

已经很普遍了。如果还有谁不明白,那就去看看MSDN查找SetWindowHook就可以了。

  不要低估了这个动态连接库的作用,它可以切入所有的进程空间,也就是可以加载到所有的游戏里面哦,只要用对,

你会发现很有用途的。这个需要你复习一下Win32编程的基础知识了。呵呵,赶快去看书吧。

  2.2 截获消息

  有些游戏的响应机制比较简单,是基于消息的,或者用什么定时器的东西。这个时候你就可以用拦截消息来实现一些

有趣的功能了。

  我们拦截消息使用的也是hook技术,里面包括了键盘消息,鼠标消息,系统消息,日志等,别的对我们没有什么大的

用处,我们只用拦截消息的回调函数就可以了,这个不会让我写例子吧。其实这个和上面的一样,都是用SetWindowHook

来写的,看看就明白了很简单的。

  至于拦截了以后做什么就是你的事情了,比如在每个定时器消息里面处理一些我们的数据判断,或者在定时器里面在

模拟一次定时器,那么有些数据就会处理两次,呵呵。后果嘛,不一定是好事情哦,呵呵,不过如果数据计算放在客户端

的游戏就可以真的改变数据了,呵呵,试试看吧。用途还有很多,自己想也可以想出来的,呵呵。

  2.3 拦截Socket包

  这个技术难度要比原来的高很多。

  首先我们要替换WinSock.DLL或者WinSock32.DLL,我们写的替换函数要和原来的函数一致才行,就是说它的函数输出

什么样的,我们也要输出什么样子的函数,而且参数,参数顺序都要一样才行,然后在我们的函数里面调用真正的

WinSock32.DLL里面的函数就可以了。

  首先:我们可以替换动态库到系统路径。

  其次:我们应用程序启动的时候可以加载原有的动态库,用这个函数LoadLibary然后定位函数入口用GetProcAddress

函数获得每个真正Socket函数的入口地址。

  当游戏进行的时候它会调用我们的动态库,然后从我们的动态库中处理完毕后才跳转到真正动态库的函数地址,这样

我们就可以在里面处理自己的数据了,应该是一切数据。呵呵,兴奋吧,拦截了数据包我们还要分析之后才能进行正确的

应答,不要以为这样工作就完成了,还早呢。等分析完毕以后我们还要仿真应答机制来和服务器通信,一个不小心就会被

封号。

  分析数据才是工作量的来源呢,游戏每次升级有可能加密方式会有所改变,因此我们写外挂的人都是亡命之徒啊,被

人愚弄了还不知道。

  2.4 截获API

  上面的技术如果可以灵活运用的话我们就不用截获API函数了,其实这种技术是一种补充技术。比如我们需要截获

Socket以外的函数作为我们的用途,我们就要用这个技术了,其实我们也可以用它直接拦截在Socket中的函数,这样更直

接。

  现在拦截API的教程到处都是,我就不列举了,我用的比较习惯的方法是根据输入节进行拦截的,这个方法可以用到

任何一种操作系统上,比如Windows 98/2000等,有些方法不是跨平台的,我不建议使用。这个技术大家可以参考

《Windows核心编程》里面的545页开始的内容来学习,如果是Win98系统可以用“Windows系统奥秘”那个最后一章来学习


- 作者: oいばらの泪o 2008年05月17日, 星期六 08:24  回复(0) |  引用(0) 加入博采

游戏外挂之:解封包
在修改游戏中做到百战百胜,是需要相当丰富的计算机知识的。有很多计算机高手就是从玩游戏,修改游戏中,逐步

对计算机产生浓厚的兴趣,逐步成长起来的。不要在羡慕别人能够做到的,因为别人能够做的你也能够!我相信你们看了

本教程后,会对游戏有一个全新的认识,呵呵,因为我是个好老师!(别拿鸡蛋砸我呀,救命啊!#¥%……*)   不过

要想从修改游戏中学到知识,增加自己的计算机水平,可不能只是靠修改游戏呀! 要知道,修改游戏只是一个验证你对

你所了解的某些计算机知识的理解程度的场所,只能给你一些发现问题、解决问题的机会,只能起到帮助你提高学习计算

机的兴趣的作用,而决不是学习计算机的捷径。


一:什么叫外挂?

  现在的网络游戏多是基于Internet上客户/服务器模式,服务端程序运行在游戏服务器上,游戏的设计者在其中创造

一个庞大的游戏空间,各地的玩家可以通过运行客户端程序同时登录到游戏中。简单地说,网络游戏实际上就是由游戏开

发商提供一个游戏环境,而玩家们就是在这个环境中相对自由和开放地进行游戏操作。那么既然在网络游戏中有了服务器

这个概念,我们以前传统的修改游戏方法就显得无能为力了。记得我们在单机版的游戏中,随心所欲地通过内存搜索来修

改角色的各种属性,这在网络游戏中就没有任何用处了。因为我们在网络游戏中所扮演角色的各种属性及各种重要资料都

存放在服务器上,在我们自己机器上(客户端)只是显示角色的状态,所以通过修改客户端内存里有关角色的各种属性是

不切实际的。那么是否我们就没有办法在网络游戏中达到我们修改的目的?回答是"否"。

  我们知道Internet客户/服务器模式的通讯一般采用TCP/IP通信协议,数据交换是通过IP数据包的传输来实现的,一

般来说我们客户端向服务器发出某些请求,比如移动、战斗等指令都是通过封包的形式和服务器交换数据。那么我们把本

地发出消息称为SEND,意思就是发送数据,服务器收到我们SEND的消息后,会按照既定的程序把有关的信息反馈给客户端

,比如,移动的坐标,战斗的类型。那么我们把客户端收到服务器发来的有关消息称为RECV。知道了这个道理,接下来我

们要做的工作就是分析客户端和服务器之间往来的数据(也就是封包),这样我们就可以提取到对我们有用的数据进行修

改,然后模拟服务器发给客户端,或者模拟客户端发送给服务器,这样就可以实现我们修改游戏的目的了。

  目前除了修改游戏封包来实现修改游戏的目的,我们也可以修改客户端的有关程序来达到我们的要求。我们知道目前

各个服务器的运算能力是有限的,特别在游戏中,游戏服务器要计算游戏中所有玩家的状况几乎是不可能的,所以有一些

运算还是要依靠我们客户端来完成,这样又给了我们修改游戏提供了一些便利。比如我们可以通过将客户端程序脱壳来发

现一些程序的判断分支,通过跟踪调试我们可以把一些对我们不利的判断去掉,以此来满足我们修改游戏的需求。 在下

几个章节中,我们将给大家讲述封包的概念,和修改跟踪客户端的有关知识。大家准备好了吗?

  游戏数据格式和存储:

  在进行我们的工作之前,我们需要掌握一些关于计算机中储存数据方式的知识和游戏中储存数据的特点。本章节是提

供给菜鸟级的玩家看的,如果你是高手就可以跳过了,如果,你想成为无坚不摧的剑客,那么,这些东西就会花掉你一些

时间;如果,你只想作个江湖的游客的话,那么这些东西,了解与否无关紧要。是作剑客,还是作游客,你选择吧!

  现在我们开始!首先,你要知道游戏中储存数据的几种格式,这几种格式是:字节(BYTE)、字(WORD)和双字(DOUBLE

WORD),或者说是8位、16位和32位储存方式。字节也就是8位方式能储存0~255的数字;字或说是16位储存方式能储存

0~65535的数;双字即32位方式能储存0~4294967295的数。

  为何要了解这些知识呢?在游戏中各种参数的最大值是不同的,有些可能100左右就够了,比如,金庸群侠传中的角

色的等级、随机遇敌个数等等。而有些却需要大于255甚至大于65535,象金庸群侠传中角色的金钱值可达到数百万。所以

,在游戏中各种不同的数据的类型是不一样的。在我们修改游戏时需要寻找准备修改的数据的封包,在这种时候,正确判

断数据的类型是迅速找到正确地址的重要条件。

  在计算机中数据以字节为基本的储存单位,每个字节被赋予一个编号,以确定各自的位置。这个编号我们就称为地址



  在需要用到字或双字时,计算机用连续的两个字节来组成一个字,连续的两个字组成一个双字。而一个字或双字的地

址就是它们的低位字节的地址。 现在我们常用的Windows 9x操作系统中,地址是用一个32位的二进制数表示的。而在平

时我们用到内存地址时,总是用一个8位的16进制数来表示它。

  二进制和十六进制又是怎样一回事呢?

  简单说来,二进制数就是一种只有0和1两个数码,每满2则进一位的计数进位法。同样,16进制就是每满十六就进一

位的计数进位法。16进制有0--F十六个数字,它为表示十到十五的数字采用了A、B、C、D、E、F六个数字,它们和十进制

的对应关系是:A对应于10,B对应于11,C对应于12,D对应于13,E对应于14,F对应于15。而且,16进制数和二进制数间

有一个简单的对应关系,那就是;四位二进制数相当于一位16进制数。比如,一个四位的二进制数1111就相当于16进制的

F,1010就相当于A。

  了解这些基础知识对修改游戏有着很大的帮助,下面我就要谈到这个问题。由于在计算机中数据是以二进制的方式储

存的,同时16进制数和二进制间的转换关系十分简单,所以大部分的修改工具在显示计算机中的数据时会显示16进制的代

码,而且在你修改时也需要输入16进制的数字。你清楚了吧?

  在游戏中看到的数据可都是十进制的,在要寻找并修改参数的值时,可以使用Windows提供的计算器来进行十进制和

16进制的换算,我们可以在开始菜单里的程序组中的附件中找到它。

  现在要了解的知识也差不多了!不过,有个问题在游戏修改中是需要注意的。在计算机中数据的储存方式一般是低位

数储存在低位字节,高位数储存在高位字节。比如,十进制数41715转换为16进制的数为A2F3,但在计算机中这个数被存

为F3A2。

  看了以上内容大家对数据的存贮和数据的对应关系都了解了吗? 好了,接下来我们要告诉大家在游戏中,封包到底

是怎么一回事了,来!大家把袖口卷起来,让我们来干活吧!

二:什么是封包?

  怎么截获一个游戏的封包?怎么去检查游戏服务器的ip地址和端口号? Internet用户使用的各种信息服务,其通讯

的信息最终均可以归结为以IP包为单位的信息传送,IP包除了包括要传送的数据信息外,还包含有信息要发送到的目的IP

地址、信息发送的源IP地址、以及一些相关的控制信息。当一台路由器收到一个IP数据包时,它将根据数据包中的目的IP

地址项查找路由表,根据查找的结果将此IP数据包送往对应端口。下一台IP路由器收到此数据包后继续转发,直至发到目

的地。路由器之间可以通过路由协议来进行路由信息的交换,从而更新路由表。

  那么我们所关心的内容只是IP包中的数据信息,我们可以使用许多监听网络的工具来截获客户端与服务器之间的交换

数据,下面就向你介绍其中的一种工具:WPE。

  WPE使用方法:执行WPE会有下列几项功能可选择:

  SELECT GAME选择目前在记忆体中您想拦截的程式,您只需双击该程式名称即可。

  TRACE追踪功能。用来追踪撷取程式送收的封包。WPE必须先完成点选欲追踪的程式名称,才可以使用此项目。 按下

Play键开始撷取程式收送的封包。您可以随时按下 | | 暂停追踪,想继续时请再按下 | | 。按下正方形可以停止撷取封

包并且显示所有已撷取封包内容。若您没按下正方形停止键,追踪的动作将依照OPTION里的设定值自动停止。如果您没有

撷取到资料,试试将OPTION里调整为Winsock Version 2。WPE 及 Trainers 是设定在显示至少16 bits 颜色下才可执行



  FILTER过滤功能。用来分析所撷取到的封包,并且予以修改。

  SEND PACKET送出封包功能。能够让您送出假造的封包。

  TRAINER MAKER制作修改器。

  OPTIONS设定功能。让您调整WPE的一些设定值。

  FILTER的详细教学

  - 当FILTER在启动状态时 ,ON的按钮会呈现红色。- 当您启动FILTER时,您随时可以关闭这个视窗。FILTER将会保

留在原来的状态,直到您再按一次 on / off 钮。- 只有FILTER启用钮在OFF的状态下,才可以勾选Filter前的方框来编

辑修改。- 当您想编辑某个Filter,只要双击该Filter的名字即可。

  NORMAL MODE:

  范例:

  当您在 Street Fighter Online ﹝快打旋风线上版﹞游戏中,您使用了两次火球而且击中了对方,这时您会撷取到

以下的封包:SEND-> 0000 08 14 21 06 01 04 SEND-> 0000 02 09 87 00 67 FF A4 AA 11 22 00 00 00 00 SEND->

0000 03 84 11 09 11 09 SEND-> 0000 0A 09 C1 10 00 00 FF 52 44 SEND-> 0000 0A 09 C1 10 00 00 66 52 44

  您的第一个火球让对方减了16滴﹝16 = 10h﹞的生命值,而您观察到第4跟第5个封包的位置4有10h的值出现,应该就

是这里了。

  您观察10h前的0A 09 C1在两个封包中都没改变,可见得这3个数值是发出火球的关键。

  因此您将0A 09 C1 10填在搜寻列﹝SEARCH﹞,然后在修改列﹝MODIFY﹞的位置4填上FF。如此一来,当您再度发出火

球时,FF会取代之前的10,也就是攻击力为255的火球了!

  ADVANCED MODE:

  范例: 当您在一个游戏中,您不想要用真实姓名,您想用修改过的假名传送给对方。在您使用TRACE后,您会发现有

些封包里面有您的名字出现。假设您的名字是Shadow,换算成16进位则是﹝53 68 61 64 6F 77﹞;而您打算用moon﹝6D

6F 6F 6E 20 20﹞来取代他。1) SEND-> 0000 08 14 21 06 01 042) SEND-> 0000 01 06 99 53 68 61 64 6F 77 00 01

05 3) SEND-> 0000 03 84 11 09 11 094) SEND-> 0000 0A 09 C1 10 00 53 68 61 64 6F 77 00 11 5) SEND-> 0000 0A

09 C1 10 00 00 66 52 44

  但是您仔细看,您的名字在每个封包中并不是出现在相同的位置上

  - 在第2个封包里,名字是出现在第4个位置上- 在第4个封包里,名字是出现在第6个位置上

  在这种情况下,您就需要使用ADVANCED MODE- 您在搜寻列﹝SEARCH﹞填上:53 68 61 64 6F 77 ﹝请务必从位置1开

始填﹞- 您想要从原来名字Shadow的第一个字母开始置换新名字,因此您要选择从数值被发现的位置开始替代连续数值﹝

from the position of the chain found﹞。- 现在,在修改列﹝MODIFY﹞000的位置填上:6D 6F 6F 6E 20 20 ﹝此为

相对应位置,也就是从原来搜寻栏的+001位置开始递换﹞- 如果您想从封包的第一个位置就修改数值,请选择﹝from the

beginning of the packet﹞

  了解一点TCP/IP协议常识的人都知道,互联网是将信息数据打包之后再传送出去的。每个数据包分为头部信息和数据

信息两部分。头部信息包括数据包的发送地址和到达地址等。数据信息包括我们在游戏中相关操作的各项信息。那么在做

截获封包的过程之前我们先要知道游戏服务器的IP地址和端口号等各种信息,实际上最简单的是看看我们游戏目录下,是

否有一个SERVER.INI的配置文件,这个文件里你可以查看到个游戏服务器的IP地址,比如金庸群侠传就是如此,那么除了

这个我们还可以在DOS下使用NETSTAT这个命令,

  NETSTAT命令的功能是显示网络连接、路由表和网络接口信息,可以让用户得知目前都有哪些网络连接正在运作。或

者你可以使用木马客星等工具来查看网络连接。工具是很多的,看你喜欢用哪一种了。

  NETSTAT命令的一般格式为:NETSTAT [选项]

  命令中各选项的含义如下:-a 显示所有socket,包括正在监听的。-c 每隔1秒就重新显示一遍,直到用户中断它。

-i 显示所有网络接口的信息。-n 以网络IP地址代替名称,显示出网络连接情形。-r 显示核心路由表,格式同"route -

e"。-t 显示TCP协议的连接情况。-u 显示UDP协议的连接情况。-v 显示正在进行的工作。


三:怎么来分析我们截获的封包?

  首先我们将WPE截获的封包保存为文本文件,然后打开它,这时会看到如下的数据(这里我们以金庸群侠传里PK店小

二客户端发送的数据为例来讲解):

  第一个文件:SEND-> 0000 E6 56 0D 22 7E 6B E4 17 13 13 12 13 12 13 67 1BSEND-> 0010 17 12 DD 34 12 12

12 12 17 12 0E 12 12 12 9BSEND-> 0000 E6 56 1E F1 29 06 17 12 3B 0E 17 1ASEND-> 0000 E6 56 1B C0 68 12 12

12 5ASEND-> 0000 E6 56 02 C8 13 C9 7E 6B E4 17 10 35 27 13 12 12SEND-> 0000 E6 56 17 C9 12

  第二个文件:SEND-> 0000 83 33 68 47 1B 0E 81 72 76 76 77 76 77 76 02 7ESEND-> 0010 72 77 07 1C 77 77

77 77 72 77 72 77 77 77 6DSEND-> 0000 83 33 7B 94 4C 63 72 77 5E 6B 72 F3SEND-> 0000 83 33 7E A5 21 77 77

77 3FSEND-> 0000 83 33 67 AD 76 CF 1B 0E 81 72 75 50 42 76 77 77SEND-> 0000 83 33 72 AC 77

  我们发现两次PK店小二的数据格式一样,但是内容却不相同,我们是PK的同一个NPC,为什么会不同呢? 原来金庸群

侠传的封包是经过了加密运算才在网路上传输的,那么我们面临的问题就是如何将密文解密成明文再分析了。

  因为一般的数据包加密都是异或运算,所以这里先讲一下什么是异或。 简单的说,异或就是"相同为0,不同为1"(

这是针对二进制按位来讲的),举个例子,0001和0010异或,我们按位对比,得到异或结果是0011,计算的方法是:0001

的第4位为0,0010的第4位为0,它们相同,则异或结果的第4位按照"相同为0,不同为1"的原则得到0,0001的第3位为0,

0010的第3位为0,则异或结果的第3位得到0,0001的第2位为0,0010的第2位为1,则异或结果的第2位得到1,0001的第1

位为1,0010的第1位为0,则异或结果的第1位得到1,组合起来就是0011。异或运算今后会遇到很多,大家可以先熟悉熟

悉,熟练了对分析很有帮助的。

  下面我们继续看看上面的两个文件,按照常理,数据包的数据不会全部都有值的,游戏开发时会预留一些字节空间来

便于日后的扩充,也就是说数据包里会存在一些"00"的字节,观察上面的文件,我们会发现文件一里很多"12",文件二里

很多"77",那么这是不是代表我们说的"00"呢?推理到这里,我们就开始行动吧!

  我们把文件一与"12"异或,文件二与"77"异或,当然用手算很费事,我们使用"M2M 1.0 加密封包分析工具"来计算就

方便多了。得到下面的结果:

  第一个文件:1 SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09SEND-> 0010 05 00 CF 26 00 00

00 00 05 00 1C 00 00 00 892 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 083 SEND-> 0000 F4 44 09 D2 7A 00

00 00 484 SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00

  第二个文件:1 SEND-> 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09SEND-> 0010 05 00 70 6B 00 00

00 00 05 00 05 00 00 00 1A2 SEND-> 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 843 SEND-> 0000 F4 44 09 D2 56 00

00 00 484 SEND-> 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 005 SEND-> 0000 F4 44 05 DB 00

  哈,这一下两个文件大部分都一样啦,说明我们的推理是正确的,上面就是我们需要的明文!

  接下来就是搞清楚一些关键的字节所代表的含义,这就需要截获大量的数据来分析。

  首先我们会发现每个数据包都是"F4 44"开头,第3个字节是变化的,但是变化很有规律。我们来看看各个包的长度,

发现什么没有?对了,第3个字节就是包的长度! 通过截获大量的数据包,我们判断第4个字节代表指令,也就是说客户

端告诉服务器进行的是什么操作。例如向服务器请求战斗指令为"30",战斗中移动指令为"D4"等。 接下来,我们就需要

分析一下上面第一个包"F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 05 00 CF 26 00 00 00 00 05 00 1C 00

00 00 89",在这个包里包含什么信息呢?应该有通知服务器你PK的哪个NPC吧,我们就先来找找这个店小二的代码在什么

地方。 我们再PK一个小喽罗(就是大理客栈外的那个咯):SEND-> 0000 F4 44 1F 30 D4 75 F6 05 01 01 00 01 00 01

75 09SEND-> 0010 05 00 8A 19 00 00 00 00 11 00 02 00 00 00 C0 我们根据常理分析,游戏里的NPC种类虽然不会超

过65535(FFFF),但开发时不会把自己限制在字的范围,那样不利于游戏的扩充,所以我们在双字里看看。通过"店小二

"和"小喽罗"两个包的对比,我们把目标放在"6C 79 F6 05"和"CF 26 00 00"上。(对比一下很容易的,但你不能太迟钝

咯,呵呵)我们再看看后面的包,在后面的包里应该还会出现NPC的代码,比如移动的包,游戏允许观战,服务器必然需

要知道NPC的移动坐标,再广播给观战的其他玩家。在后面第4个包"SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27

35 01 00 00"里我们又看到了"6C 79 F6 05",初步断定店小二的代码就是它了!(这分析里边包含了很多工作的,大家

可以用WPE截下数据来自己分析分析)

  第一个包的分析暂时就到这里(里面还有的信息我们暂时不需要完全清楚了)

  我们看看第4个包"SEND-> 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00",再截获PK黄狗的包,(狗会

出来2只哦)看看包的格式:SEND-> 0000 F4 44 1A DA 02 0B 4B 7D F6 05 02 27 35 01 00 00SEND-> 0010 EB 03 F8

05 02 27 36 01 00 00

  根据上面的分析,黄狗的代码为"4B 7D F6 05"(100040011),不过两只黄狗服务器怎样分辨呢?看看"EB 03 F8

05"(100140011),是上一个代码加上100000,呵呵,这样服务器就可以认出两只黄狗了。我们再通过野外遇敌截获的数

据包来证实,果然如此。

  那么,这个包的格式应该比较清楚了:第3个字节为包的长度,"DA"为指令,第5个字节为NPC个数,从第7个字节开始

的10个字节代表一个NPC的信息,多一个NPC就多10个字节来表示。

  大家如果玩过网金,必然知道随机遇敌有时会出现增援,我们就利用游戏这个增援来让每次战斗都会出现增援的NPC

吧。

  通过在战斗中出现增援截获的数据包,我们会发现服务器端发送了这样一个包:F4 44 12 E9 EB 03 F8 05 02 00 00

03 00 00 00 00 00 00 第5-第8个字节为增援NPC的代码(这里我们就简单的以黄狗的代码来举例)。 那么,我们就利用

单机代理技术来同时欺骗客户端和服务器吧!

  好了,呼叫NPC的工作到这里算是完成了一小半,接下来的事情,怎样修改封包和发送封包,我们下节继续讲解吧。


四:怎么冒充"客户端"向"服务器"发我们需要的封包?

  这里我们需要使用一个工具,它位于客户端和服务器端之间,它的工作就是进行数据包的接收和转发,这个工具我们

称为代理。如果代理的工作单纯就是接收和转发的话,这就毫无意义了,但是请注意:所有的数据包都要通过它来传输,

这里的意义就重大了。我们可以分析接收到的数据包,或者直接转发,或者修改后转发,或者压住不转发,甚至伪造我们

需要的封包来发送。

  下面我们继续讲怎样来同时欺骗服务器和客户端,也就是修改封包和伪造封包。 通过我们上节的分析,我们已经知

道了打多个NPC的封包格式,那么我们就动手吧!

  首先我们要查找客户端发送的包,找到战斗的特征,就是请求战斗的第1个包,我们找"F4 44 1F 30"这个特征,这是

不会改变的,当然是要解密后来查找哦。 找到后,表示客户端在向服务器请求战斗,我们不动这个包,转发。 继续向下

查找,这时需要查找的特征码不太好办,我们先查找"DA",这是客户端发送NPC信息的数据包的指令,那么可能其他包也

有"DA",没关系,我们看前3个字节有没有"F4 44"就行了。找到后,我们的工作就开始了!

  我们确定要打的NPC数量。这个数量不能很大,原因在于网金的封包长度用一个字节表示,那么一个包可以有255个字

节,我们上面分析过,增加一个NPC要增加10个字节,所以大家算算就知道,打20个NPC比较合适。

  然后我们要把客户端原来的NPC代码分析计算出来,因为增加的NPC代码要加上100000哦。再把我们增加的NPC代码计

算出来,并且组合成新的封包,注意代表包长度的字节要修改啊,然后转发到服务器,这一步在编写程序的时候要注意算

法,不要造成较大延迟。

  上面我们欺骗服务器端完成了,欺骗客户端就简单了。

  发送了上面的封包后,我们根据新增NPC代码构造封包马上发给客户端,格式就是"F4 44 12 E9 NPC代码 02 00 00

03 00 00 00 00 00 00",把每个新增的NPC都构造这样一个包,按顺序连在一起发送给客户端,客户端也就被我们骗过了

,很简单吧。

  以后战斗中其他的事我们就不管了,尽情地开打吧。


[本日志由 looo 于 2005-02-10 01:21 PM 编辑]

looo 于 2005-02-10 01:16 PM 发表评论:

- 作者: oいばらの泪o 2008年05月17日, 星期六 08:17  回复(0) |  引用(0) 加入博采

用C#2.0实现网络蜘蛛(WebSpider)
 摘要:本文讨论了如何使用C#2.0实现抓取网络资源的网络蜘蛛。使用这个程序,可以通过一个入口网址(如http://www.comprg.com.cn)来扫描整个互联网的网址,并将这些扫描到的网址所指向的网络资源下载到本地。然后可以利用其他的分析工具对这些网络资源做进一步地分析,如提取关键词、分类索引等。也可以将这些网络资源作为数据源来实现象Google一样的搜索引擎。

  关键词:C#2.0Html网络蜘蛛, 键树正则表达式

  一、引言

  在最近几年,以Google为首的搜索引擎越来越引起人们的关注。由于在Google出现之前,很多提供搜索服务的公司都是使用人工从网络上搜集信息,并将这些信息分类汇总后作为搜索引擎的数据源。如yahoo公司一开始就是通过数千人不停地从网上搜集供查询的信息。这样做虽然信息的分类会很人性化,也比较准确,但是随着互联网信息爆炸式地增长,通过人工的方式来搜集信息已经不可能满足网民对信息的需求了。然而,这一切随着Google的出现而得到了彻底改变。Google一反常规的做法,通过程序7*24地从网上不停地获取网络资源,然后通过一些智能算法分析这些被下载到本地的网络资源,最后将这些分析后的数据进行索引后就形成了一套完整的基本上不需要人工干预的搜索引擎。使用这种模式的搜索引擎甚至可以在几天之内就可获取Internet中的所有信息,同时也节省了大量的资金和时间成本。而这种搜索引擎最重要的组成部分之一就是为搜索引擎提供数据源的网络蜘蛛。也就是说,实现网络蜘蛛是实现搜索引擎的第一步,也是最重要的一步。

  二、网络蜘蛛的基本实现思想和实现步骤

  网络蜘蛛的主要作用是从Internet上不停地下载网络资源。它的基本实现思想就是通过一个或多个入口网址来获取更多的URL,然后通过对这些URL所指向的网络资源下载并分析后,再获得这些网络资源中包含的URL,以此类推,直到再没有可下的URL为止。下面是用程序实现网络蜘蛛的具体步骤。

  1. 指定一个(或多个)入口网址,并将这个网址加入到下载队列中(这时下载队列中只有一个或多个入口网址)。

  2. 负责下载网络资源的线程从下载队列中取得一个或多个URL,并将这些URL所指向的网络资源下载到本地(在下载之前,一般应该判断一下这个URL是否已经被下载过,如果被下载过,则忽略这个URL)。如果下载队列中没有URL,并且所有的下载线程都处于休眠状态,说明已经下载完了由入口网址所引出的所有网络资源。这时网络蜘蛛会提示下载完成,并停止下载。

  3. 分析这些下载到本地的未分析过的网络资源(一般为html代码),并获得其中的URL(如标签中href属性的值)。

  4. 将第3步获得的URL加入到下载队列中。并重新执行第2步。

  三、实现数据的输入输出

  从实现网络蜘蛛的步骤中我们可以看出,下载队列的读、写URL的操作一直贯穿于整个系统中。虽然这个下载队列可以用.Queue类实现,但是各位读者要清楚地知道,在互联网上的URL可不是几十个、几百个这么少。而是以千万计的。这么多的URL显然不能保存在内存中的Queue对象中。因此,我们需要将它保存在容量更大的存储空间中,这就是硬盘。

  本文采用了一个普通的文本文件来保存需要下载和分析的URL(这个文本文件也就是下载队列)。存储格式是每一行为一个URL。既然将URL都保存在了文本文件中,就需要对这个文本文件进行读写。因此,在本节实现了一个用于操作这个文本文件的FileIO类。

  在实现FileIO类之前,先来说一下要如何操作这个文本文件。既然要将这个文件作为队列使用,那么就需要对这个文件进行追加行和从文件开始部分读取数据操作。让我们首先来实现向文件中追加行操作。实现代码如下:

  向文件中追加行的实现代码

  


// 这两个变量为类全局变量
  private FileStream fsw;
  private StreamWriter sw;
  // 创建用于向文件中追加行的文件流和StreamWriter对象
  public void OpenWriteFile(string file)
  {
  if (!File.Exists(file)) // 如果文件不存在,先创建这个文件
  File.Create(file).Close();
  // 以追加模式打开这个文件
  fsw = new FileStream(file, FileMode.Append ,FileAccess.Write, FileShare.ReadWrite);
  // 根据创建的FileStream对象来创建StreamWriter对象
  sw = new StreamWriter(fsw);
  }
  // 关闭写文件流
  public void CloseWriteFile()
  {
  if (fsr != null)
  fsw.Close();
  }
  // 向文件中追加一行字符串
  public void WriteLine(string s)
  {
  sw.WriteLine(s);
  sw.Flush(); // 刷新写入缓冲区,使这一行对于读文件流可见
  }
  在实现上述的代码时要注意,在创建FileStream对象时,必须使用FileShare.ReadWrite,否则这个文件无法被两个或两个以上的Stream打开,也就是说下面要介绍的读文件流将无法操作这个被写文件流打开的文件。从文件中读取行的实现代码如下:

  从文件中读取行的实现代码

 


 // 这两个变量为类全局变量
  private FileStream fsr;
  private StreamReader sr;
  // 创建用于读取文件行的文件流和StreamWriter对象
  public void OpenReadFile(string file)
  {
  if (!File.Exists(file)) // 如果文件不存在,首先创建这个文件
  File.Create(file).Close();
  fsr = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Read,
  FileShare.ReadWrite);
  sr = new StreamReader(fsr);
  }
  // 关闭读文件流
  public void CloseReadFile()
  {
  if(fsr != null)
  fsr.Close();
  }
  // 从文件中读取一行
  public string ReadLine()
  {
  if(sr.EndOfStream) // 如果文件流指针已经指向文件尾部,返回null
  return null;
  return sr.ReadLine();
  }
  除了上述的读写文件的代码外,FileIO还提供了一个IsEof方法用来判断文件流指针是否位于文件尾部。IsEof方法的实现代码如下如下:

  IsEof方法的实现代码

 


 // 用于判断文件流指针是否位于文件尾部
  public bool IsEof()
  {
  return sr.EndOfStream;
  }
  FileIO类不仅仅用于对下载队列的读写。在后面我们还会讲到,网络蜘蛛通过多线程下载网络资源时,每一个线程将自己下载的网络资源保存在属于自己的一个目录中。每个这样的目录都有一个index.txt文件,这个文件保存了当前目录的网络资源的URL。向index.txt文件中追加URL也用到了FileIO(index.txt不需要读取,只需要不断地追加行)。

四、线程类的实现

  要想使网络蜘蛛在有限的硬件环境下尽可能地提高下载速度。最廉价和快捷的方法就是使用多线程。在.net framework2.0中提供了丰富的线程功能。其中的核心线程类是Thread。一般可使用如下的代码创建并运行一个线程:

  在C#中使用线程的演示代码

  


private void fun()
  {
  // 线程要执行的代码
  }
  public void testThread()
  {
  Thread thread;
  thread = new Thread(fun); // 创建一个Thread对象,并将fun设为线程运行的方法
  thread.Start(); // 运行一个线程
  }
  虽然上面的代码比较简单地创建并运行了一个线程,但是这段代码看起来仍然不够透明,也就是客户端在调用线程时仍然需要显式地使用Thread类。下面我们来实现一个用于创建线程的MyThread类。C#中的任何类只需要继承这个类,就可以自动变成一个线程类。MyThread类的代码如下:

  MyThread类的实现代码

  


// 任何C#类继承MyThread后,就会自动变成一个线程类
  class MyThread
  {
  private Thread thread;
  public MyThread()
  {
  thread = new Thread(run); // 创建Thread对象
  }
  // 用于运行线程代码的方法,MyThread的子类必须覆盖这个方法
  public virtual void run()
  {
  }
  public void start()
  {
  thread.Start(); // 开始运行线程,也就是开始执行run方法
  }
  // 使当前线程休眠millisecondsTimeout毫秒
  public void sleep(int millisecondsTimeout)
  {
  Thread.Sleep(millisecondsTimeout);
  }
  }
  我们可参照如下的代码使用MyThread类:

  测试的ThreadClass类的代码

 


 class ThreadClass : MyThread
  {
  public override void run()
  {
  // 要执行的线程代码
  }
  }
  // 测试ThreadClass类
  public void testThreadClass()
  {
  ThreadClass tc = new ThreadClass();
  tc.start(); // 开始运行线程,也就是执行run方法
  }
  各位读者可以看看,上面的代码是不是要比直接使用Thread类更方便、直观、易用,还有些面向对象的感觉!

  五、用多线程下载网络资源

  一般来说,网络蜘蛛都是使用多线程来下载网络资源的。至于如何使用多线程来下载,各个版本的网络蜘蛛不尽相同。为了方便和容易理解,本文所讨论的网络蜘蛛采用了每一个线程负责将网络资源下载到一个属于自己的目录中,也就是说,每一个线程对应一个目录。而在当前目录中下载的网络资源达到一定的数目后(如5000),这个线程就会再建立一个新目录,并从0开始计数继续下载网络资源。在本节中将介绍一个用于下载网络资源的线程类DownLoadThread。这个类的主要功能就是从下载队列中获得一定数量的URL,并进行下载和分析。在DownLoadThread类中涉及到很多其他重要的类,这些类将在后面的部分介绍。在这里我们先看一下DownLoadThread类的实现代码。

  


DownLoadThread类的代码
  class DownLoadThread : MyThread
  {
  // ParseResource类用于下载和分析网络资源
  private ParseResource pr = new ParseResource();
  private int currentCount = 0; // 当前下载目录中的网页数
  // 用于向每个线程目录中的index.txt中写当前目录的URL
  private FileIO fileIO = new FileIO();
  private string path; // 当前的下载目录(后面带“\")
  private string[] patterns; // 线程不下载符合patterns中的正则表达式的URL
  public bool stop = false; // stop为true,线程退出
  public int threadID; // 当前线程的threadID,用于区分其他的线程
  public DownLoadThread(string[] patterns)
  {
  pr.findUrl += findUrl; // 为findUrl事件赋一个方法
  this.patterns = patterns;
  }
  // 这是一个事件方法,每获得一个URL时发生
  private void findUrl(string url)
  {
  Common.addUrl(url); // 将获得的URL加到下载队列中
  }
  private void openFile() // 打开下载目录中的index.txt文件
  {
  fileIO.CloseWriteFile();
  fileIO.OpenWriteFile(path + Common.indexFile);
  }
  public override void run() // 线程运行方法
  {
  LinkedList urls = new LinkedList();
  path = Common.getDir(); // 获得下载目录
  openFile();
  while (!stop)
  {
  // 当下载队列中没有URL时,进行循环等待
  while (!stop && urls.Count == 0)
  {
  Common.getUrls(urls, 20); // 从下载队列中获得20个url
  if (urls.Count == 0) // 如果未获得url
  {
  // 通知系统当前线程已处于等待状态,
  // 如果所有的线程都处于等待状态,
  // 说明所有的网络资源都被下载完了
  Common.threadWait(threadID);
  sleep(5000); // 当前线程休眠5秒
  }
  }
  StringBuilder sb = new StringBuilder();
  foreach (string url in urls) // 循环对这20个url进行循环下载分析
  {
  if (stop) break;
  // 如果当前下载目录的资源文件数大于等于最大文件数目时,
  // 建立一个新目录,并继续下载
  if (currentCount >= Common.maxCount)
  {
  path = Common.getDir();
  openFile();
  currentCount = 0; // 目录
  }
  // 每个下载资源文件名使用5位的顺序号保存(没有扩展名),
  // 如00001、00002。下面的语句是格式化文件名
  string s = string.Format("{0:D5}", currentCount + 1);
  sb.Remove(0, sb.Length);
  sb.Append(s);
  sb.Append(":");
  sb.Append(url);
  try
  {
  // 下载和分析当前的url
  pr.parse(url, path + s, patterns);
  Common.Count++;
  // 将当前的url写入index.txt
  fileIO.WriteLine(sb.ToString());
  currentCount++;
  }
  catch (Exception e)
  {
  }
  }
  urls.Clear();
  }
  }
  }
  }

- 作者: oいばらの泪o 2008年05月16日, 星期五 11:39  回复(0) |  引用(0) 加入博采

网络编程:网络蜘蛛
大众网络报 张黎
  编者按:经常去雅虎、搜狐等网站搜索信息的读者一定有这样的疑问:如此庞大的网页信息,到底是如何被这 些网站所收集到的呢?难道都是人工登记并整理的吗?当然不是。这些搜索引擎能够快速地找到如此之多的信 息,和网络蜘蛛的应用是分不开的。

  网络蜘蛛可以算得上是为Internet而开发的最有用处的工具之一。时至今日,要想从以千万计的各不相同 的站点中获取信息,舍网络蜘蛛之外,焉有他哉?

  一个典型的网络蜘蛛(例如雅虎)工作的方式,是查看一个页面,并从中找到相关信息, 然后它再 从该页面的所有链接中出发,继续寻找相关的信息。以此类推,直至穷尽。很快地,就可以在数据库中获得成 千上万的页面和信息。这样的工作方式就如同一张向外发散的蜘蛛网,这正是“网络蜘蛛”这个名称的由来。

  接下来让我们看看如何建立一个网络蜘蛛。在此之前,我们先要了解几个概念。

一、基本原理

  我们可以用网络蜘蛛搜寻很多东西。事实上,现在有一些特别用途的商用网络蜘蛛,这些软件为它们的开 发者赚取了大把的钞票,比如Altavista科技的一份许可证,就价值30万美元。以下是一个网络蜘蛛的基础原 理:

  * 从各个消息来源收集信息

  从技术角度讲,一个网络蜘蛛应该可以不受限制地从任意来源获取信息。来源多多益善。

  * 准确度

  不管是谁,遇见这样的事情肯定都会崩溃——搜索引擎向你返回了一百万个结果,可是,只有最后两个是 你需要的(这还算好的,如果是中间的两个呢?)。所以好的网络蜘蛛对其返回的结果应该有足够的准确度, 而且在有些情况下,还要有特定的功能,也就是说,只返回特定类型的信息——比如www.enfused.com的专为 搜索游戏设计的网络蜘蛛,就只返回与游戏相关的东西。

  * 相对更新

  这依赖于你所使用的技术(下面我们会专门提到),网络蜘蛛应该找回更新后的信息,或者至少是比较新 的信息。如果网络蜘蛛总是找回一些几年前的陈芝麻烂谷子,那你一定会比系统先一步崩溃。

  * 相对快速

  这就不用多说了,如果没有足够的速度,那你的网络蜘蛛再怎么准确,也是白搭。


二、基本技术

  有好几种方法可以构建网络蜘蛛。第一种,称之为常规网络蜘蛛,只是简单地进行页面寻找,搜索并获得 你想要的东西。例如,用一个短语作为关键词进行搜索。第二种,特殊网络蜘蛛,只寻找页面的特定部分。这 种网络蜘蛛在某些特定场合很有用(比如,你只想获得某一个站点内的新闻标题)。

  常规网络蜘蛛是两者中相对简单的一种。首先,你不需要预先知道目标页面的情况。只需要在该页面中, 以及在与其链接的页面中,寻找你要的关键词就可以了。你还可以在功能中设定,忽略掉那些在同一站点下的 链接,从而保证每一个结果都来源于不同的站点。

  与之相对应,一个特定的网络蜘蛛通常要求你预先知道一些目标页面的情况,例如表格规划等。举个例子 ,如果你搜寻的是一个页面中的新闻标题,你应该先知道限定此标题的HTML标记。如此你才可以直接搜索页面 中正确的部分。在这种情况下,是否具备搜索该页面的所有链接的功能显得不是特别重要,因为你的网络蜘蛛 很可能在别的页面中无法找到标记,不能进行工作。

  运行网络蜘蛛的时间也有所不同:你可以预先运行,也可以实时运行。预先运行意味着当你的网络蜘蛛运 行时,所有搜集到的信息都存贮在一个数据库中,以备以后使用。很明显,如此你将不会获得最新的数据,但 是如果你经常运行网络蜘蛛,这个问题也不会有什么大碍。

  实时运行意味着你每次运行网络蜘蛛所获得的信息都不会被保存下来,你只能现找现用。例如,如果你在 站点设置了搜索功能,在实时状态下使用网络蜘蛛,则无论何时,只要有用户输入一个关键词并点下“发送” 按钮,你的网络蜘蛛就将运行,而不是仅仅访问数据库。尽管这可以保证你的数据总是最新的,但是却不是大 多数站点的首选,因为网络蜘蛛本身运行和返回数据都需要时间——而时间就是金钱呀!当然,所查找的资料 具有高度时间敏感性的时候例外。


三、构建网络蜘蛛

  那么如何用ASP构建网络蜘蛛呢?答案是:Internet transfer control (ITC)。这个由 微软提供的控件,将使你能够通过ASP程序访问Internet资源。你可以用ITC搜寻Web页面,访问FTP服务器,甚 至可以发送邮件标题。在本文里,我们将着重讨论搜寻Web页面的功能。

  有几个缺陷必须先说明一下。第一,ASP无权访问Windows的注册表,这就使某些ITC正常存储的常量和数 值不可用。通常你可以通过设置ITC为“不使用默认值”来解决这个问题,这就需要你在运行过程中指明每一 次的值。

  另一个更严重的问题是关于许可证书的。由于ASP不具备调用License Manager(一项Windows中的功 能,可以保证组件和控件的合法使用)的功能,那么当License Manager检查当前组件的密钥密码,并将 其与Windows注册表进行比较后,如果发现它们不同,该组件将不会工作。因此,当你想把ITC配置到另一台没 有所需密钥的计算机上时,将导致ITC崩溃。解决的办法之一是将ITC捆绑到另一个VB组件中,由VB组件复制 ITC的路径和工具,从而进行配置。这项工作很麻烦,但不幸的是,它是必不可少的。

  下面是一些例子:

  你可以用下面的编码建立ITC:

set Inet1 = CreateObject("InetCtls.Inet")
Inet1.protocol = 4   'HTTP
Inet1.accesstype = 1  'Direct connection to internet
Inet1.requesttimeout = 60'in seconds
Inet1.URL = strURL
trHTML = Inet1.OpenURL'grab HTML page

  现在strHTML保存着strURL指向的整个页面的HTML内容。要建立一个常规网络蜘蛛,你现在只需要调用  instr() 功能来看看你寻找的串是否在当前位置即可。你也可以按照href标记寻找,解析当前的 URL,然后把它设置到Internet 控件的属性中去,接着再继续打开另一个页面。用来查看所有链接的最 好方法是使用递归。

  要注意的是,尽管这种方法很易于实行,却不是非常准确和强大。今天的许多搜索引擎都可以进行额外的 逻辑检查,例如计算一个页面中某一短语重复的次数,相关字词的近似程度等,有些甚至可以用来判断所搜寻 的语段与上下文的关系。这些功能将留待我们的读者们自己去摸索。


四、特定网络蜘蛛

  相对的,一个特定网络蜘蛛要复杂一些。如我们早先提到的,一个特定网络蜘蛛会搜寻一个页面的特定部 分,因而要求预先知道该部分相关的情况。让我们先看看下面的HTML:

   <HTML><HEAD><TITLE>My News Page</TITLE><META Name=&quo t;keywords" Content="News, headlines"><META Name="descr iption" Content="The current news headlines."></HEAD> ;<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF3300 "VLINK="#CC0000" ALINK="#0000FF"><p><h3>Headlines&l t;/h3></p><!--put headlines here--><a href="/news/8094.asp ">Stocks prices fall</a><a href="/news/8095.asp">Ne w movies today</a><a href="/news/8096.asp">Bush and&nb sp;Gore to debate tonight</a><a href="/news/8097.asp"> Fall TV lineup</a><!--end headlines--></BODY></HTML>


  在这个页面内,我们只关心位于“put headlines here”和 “end headlines”这 两个标记之间的东西。你可以构建一个只返回该区域查找结果的功能设置:

Function GetText(strText, strStartTag, strEndTag)
dim intStart
intStart = instr(1, strText, strStartTag, vbtextcompare)
if intStart then
intStart = intStart + len(strStartTag)
intEnd = InStr(intStart + 1, strText, strEndTag, vbtextcompar e)
GetText = Mid(strText, intStart + 1, intEnd - intStart&n bsp;- 1)
else
GetText = " "
end if
End Function

  按照上面构建ITC控件的例子,你可以很容易地将strHTML中的“ <!--put headlines here-->”和 “<!--end headlines-->”作为参数传 送到GetText中。

  要注意,用于开始和结束的标记都不一定要是实际的HTML专用标记——它们可以是你想使用的任何文本界 定符。在通常情况下,你不容易找到好的HTML标记来界定搜寻区域。你只能使用比较方便称手的标记——例如 ,你的首尾标记可以分别如下:

 strStartTag = "/td><td><font face="arial" size=&q uot;2"><p><b><u>"
 strEndTag = "<p></td></tr><tr><td><o:ums>&quo t;

  一定要确定搜索的是HTML页中比较独特的标识,这样你才可以准确地获得你需要的东西。你也可以按照你 所返回的文本部分中的链接进行搜寻,不过如果你不知道那些页面的格式,你的网络蜘蛛将无功而返。


五、保存信息

  在大多数情况下,你会要求将收集到的信息保存在一个数据库中,以备以后使用。你的需求也许包括很广 泛的内容,但是在此之前,你要记住以下几件事:

  在你的数据库中查找最新信息

  如果你经常使用网络蜘蛛去查找一个站点内的新闻标题,你要先确定比较新的标题已经存在于数据库内。 然后将其与网络蜘蛛返回的结果相比较,只添加更新过的部分。这样可以防止你保存一大堆重复数据。

  更新信息

  也许你根本就不想从外部向数据库中添加新信息。比如,如果你维护的是一个美国各州人口的网上索引, 你只需要在数据库内部更新——你将不需要在表格内插入新的信息。

  保存所需信息
如果你在查找标题,要确定你也同时查找了该标题指向的链接,并将其保存下来。如果没有链接,你 也应该建立一个。例如,如果我从www.yoursite.com查找标题,并在www.mysite .com演示,而该标题与一篇在站点之外的文章有链接,那么我必须先保存http://www.you rsite.com这一链接,然后再保存其它链接到数据库内,这些链接才可以正常访问。


  六、结论

  我们已经简要介绍了如何构建一个比较完整的网络蜘蛛。所有的基本功能都已涉及。现在你需要做的就是 再在里面加上你自己的东西。

  这一类功能将被应用在一个COM对象或者一个独立的应用软件内。在ASP中设置这项功能非常方便, 但是你应该将你的编码移到另外的地方,以提高速度和安全性。而且这样也可以令其更容易被打包和传送。

- 作者: oいばらの泪o 2008年05月16日, 星期五 11:25  回复(0) |  引用(0) 加入博采

牛逼顿——评价牛顿的搞笑文,超强。
3月28号是牛顿的忌日,但是知道的人很少,我们毕竟更关心沈殿霞和张国荣。其实牛
顿老师在科学圈里曾经很有权势,被女王封了爵位成了贵族,官至皇家造币局局长兼皇
家学会会长。如果阿尔伯特没有辞了以色列总统的话和他有一拼。说他有权势并不仅是
官大,主要是贡献大。如果17世纪就有诺贝尔奖的话,牛顿老师至少能连续垄断4届物
理学奖(分光计;力学体系的构建;反射望远镜;万有引力),同时为了表彰他在炼金
方面的造诣,再奉送他一届化学奖。而且这孙子鼓捣出了流数术,所以菲尔兹数学奖也
要给他。要知道,他的这些发现基本都是在26岁以前获得的,30岁以后牛顿就开始玩票
了,成天琢磨上帝和炼金,以及怎样把莱布尼茨搞臭,捎带手的把以前的发现整理成书
。所以你能想象到他在当时的欧洲是如何的一呼万应,敢跟他叫板的只有莱布尼茨和大
主教贝克莱。牛老师死的时候,全英国的名流以给他扶柩为荣,全欧洲的名流蜂拥伦敦
。来自法国的傻逼文科生伏尔泰在国葬现场大受刺激,回去就写了首诗,嫉妒之情溢于
言表。

牛顿老师的一生是天才的一生,战斗的一生,也是孤独的一生。一辈子没有朋友,也没
有结过婚,很可能到死都是处男,关于牛顿是否处男的问题,由于篇幅过长,我将在另
一篇文中论证。当然他肯定不会孤独,因为科学的世界里乐趣无限,快感连连。出乎世
俗想象的是,科学其实远比任何娘们儿都风骚,玩科学比玩女人爽得多,得到一个成果
所获得的高潮强烈而持久,不仅有快感,更有巨大的自我认同感,远胜于那几秒寒颤之
后无边的空虚与落寞。所以陈景润其实是沉溺于美色不能自拔,身体弱架不住高潮过度
被爽死了。

牛顿老师茕茕孑立,形影相吊的原因是多方面的。首先他生性孤傲,自恃高才,瞅谁都
是傻逼,当然不会真心跟傻逼交朋友。同时在他眼里人是不分男女的,只有傻逼和巨傻
逼两种,所以他对女色没兴趣也就可以理解了。有婚介中心给他介绍过几个名媛,拾掇
拾掇都是当王妃的坯子,但一见面就受不了牛顿的牛逼烘烘和不知所云。比如有次相亲
,他把姑娘的手指头塞进了烟斗。

另一方面是外在的,不光他不愿意交朋友,也没有人真正想跟牛顿当朋友,结交他的人
都是有目的的。人们对他只有敬畏和仰慕,并不真的喜欢他。这道理其实很浅显,绝大
部分人都热衷于跟比自己傻的人待着,很少有人愿意在人精的身边衬托自己的二逼。所
以好多人都喜欢小动物和小孩子,就是因为这些东西够傻。不少姑娘一见到小猫小狗小
人儿都会迫不及待的搂抱,接踵而至的就是很嗲的说好可爱欧~,听得我阴毛都竖起来
了。有时候可爱和憨态可掬的潜台词就是弱智。小猴子也很好玩,喜欢的人就少多了,
因为猴子机灵到能戏弄人,那些人没有驾驭猴子的自信。同理,喜欢小孩的都是喜欢他
们的单纯与缺心眼,在他们眼里,小孩跟小动物没有本质区别,也都是四条腿走路,露
着随时拉撒。如果遇到一个小天才,3岁就会心算三位数乘法或者知道傻逼二字的
正确写法,她们一定会骇破了胆。所以那些喜欢养猫狗的女士们别再标榜自己有爱心了
,你们其实比谁都缺德。我从不喜欢猫狗,这是因为我敬畏大自然的生灵而不忍戏弄它
们;我也不喜欢小孩,因为我把他们当作一个大写的人而不是小畜生看待。

大家不喜欢牛顿的另一个原因是他性格暴戾乖张。长年在他身边的人回忆说,牛顿在人
前只笑过两回,其中一次还是嘲笑:有人问他,欧几里得的《几何原本》那么老朽,不
知道还有什么价值。牛顿闻听放声大笑。而且他人品太差,跟谁都打架。众所周知他从
小就有校园暴力的记录,胖子同学不小心踩了他的风车,他抬手就把胖子打哭了,我们
的教科书居然说这是他有志气的表现。长大了不以拳脚论高下,他就雇用枪手大骂莱布
尼茨,甚至不惜化名亲自去骂,人品至此真是无以复加。莱布尼茨若不是脸皮厚早就跟
纳什一样疯了,而且牛顿老师肯定会拍个片子叫《丑陋心灵》继续恶心人家。

关于牛顿的另一个谎言是他的谦虚,证据就是牛顿老师说过两段著名的话,一段是站在
巨人肩膀上,另一段是海边捡石头子。这确实很有迷惑性,我第一次听到后感动的直冒
鼻涕泡。但任何话语都是有语境的,巨人肩膀那一句的语境是这样的:胡克其实早就发
现了万有引力定律并推导出了正确的公式,但由于数学不好,他只能勉强解释行星绕日
的圆周运动,而且他没有认识到支配天体运行的力量其实是普遍存在的,是“万有”的
。第谷早在100年前就发现了行星的公转其实是椭圆运动,开普勒甚至提出了行星运动
三定律。所以科学界对胡克的成果不太重视。后来数学小狂人牛顿用微积分极其圆满的
解决了这个问题并把他提出的力学三条基本定律成功推广到了星系空间,改变了自从亚
里士多德以来公认的天地不一的旧观点,被科学界奉为伟大的发现。于是胡克大怒,指
责牛顿剽窃了自己的成果。牛顿尖酸刻薄的回敬道:是啊,我他妈还真是站在巨人的肩
膀上呢!这本是一句反语,至少不是真的想客气一下。几百年后罗永浩说自己只是站在
巨人的肩膀上也是这意思。但后人出于塑造完人的目的,只保留了孤立的原话而去掉了
语境,变成了一句彻头彻尾的谦辞。

牛顿老师人品差,不谦虚,没朋友,按现在的说法这是典型的高智商低情商,事业不会
成功。但我们也发现,当智商高到一定程度的时候是可以取代情商的。所以那些说自己
情商低的所谓天才们,你们没成功只是他妈的还不够聪明而已,怨不着人家情商。要知
道牛顿是个遗腹子和早产儿,出生时体重不到5斤,没吃过DHA和RHA配方的奶粉。亲娘
改嫁后跟文盲姥姥度过无聊的童年,没有任何的早期智力开发和学前启蒙,7岁上学以
前脑子里空空如也,牛妈妈对他的期望仅仅是认识点字然后回家务农。但是牛顿上中学
后已经熟练掌握了拉丁语希腊语西班牙语和英语,然后被推荐进了剑桥,20出头就当了
卢卡斯教席的终身教授。

晚年的牛顿除了升官发财再无其他骄傲之处,而且官迷心窍,没退休一直干到85岁寿终
。当然他并没闲着,写了150万字的神学著作,同时一心扑在化学事业上,在家里盖了
窑子,拿出年轻时搞物理的劲头玩命试验。但这次他的出发点就错了,总是希望从黄铜
和煤渣中提炼出黄金。要知道化学反应只改变分子并不能改变原子,能给原子做变性手
术的只能是核反应。他违背了物质不灭的化学定律,所以虾米了。

最后,说两段悼词。一段是他的墓志铭:伊萨克牛顿爵士,安葬在这里。他以超乎常人
的智力,第一个证明了行星的运动与形状;彗星轨道与海洋的潮汐。他孜孜不倦地研究
,光线的各种不同的折射角,颜色所产生的种种性质。让人类欢呼,曾经存在过这样一
位,伟大的人类之光。另一段是英国诗人写的:自然和自然的规律隐藏在茫茫黑夜之中
。上帝说:让牛顿降生吧。于是一片光明。

不知道为什么,一想到这里,我总是有点感动。

- 作者: oいばらの泪o 2008年05月10日, 星期六 06:02  回复(0) |  引用(0) 加入博采

数据挖掘【转载】

数据挖掘
开放分类: 数据库、网络、电脑、计算机、知识发现

 目录
• 什么是数据挖掘
• 数据挖掘的起源
• 数据挖掘能做什么
• 数据挖掘的一般流程
• 数据挖掘的商业背景
• 数据挖掘技术实现
• 数据挖掘与数据仓库融合发展

 

什么是数据挖掘


    数据挖掘(Data Mining),又称为数据库中的知识发现(Knowledge Discovery in Database, KDD),就是从大量数据中获取有效的、新颖的、潜在有用的、最终可理解的模式的非平凡过程,简单的说,数据挖掘就是从大量数据中提取或“挖掘”知识。

    并非所有的信息发现任务都被视为数据挖掘。例如,使用数据库管理系统查找个别的记录,或通过因特网的搜索引擎查找特定的Web页面,则是信息检索(information retrieval)领域的任务。虽然这些任务是重要的,可能涉及使用复杂的算法和数据结构,但是它们主要依赖传统的计算机科学技术和数据的明显特征来创建索引结构,从而有效地组织和检索信息。尽管如此,数据挖掘技术也已用来增强信息检索系统的能力。

数据挖掘的起源


    为迎接前一节中的这些挑战,来自不同学科的研究者汇集到一起,开始着手开发可以处理不同数据类型的更有效的、可伸缩的工具。这些工作建立在研究者先前使用的方法学和算法之上,在数据挖掘领域达到高潮。特别地,数据挖掘利用了来自如下一些领域的思想:(1) 来自统计学的抽样、估计和假设检验,(2) 人工智能、模式识别和机器学习的搜索算法、建模技术和学习理论。数据挖掘也迅速地接纳了来自其他领域的思想,这些领域包括最优化、进化计算、信息论、信号处理、可视化和信息检索。

    一些其他领域也起到重要的支撑作用。特别地,需要数据库系统提供有效的存储、索引和查询处理支持。源于高性能(并行)计算的技术在处理海量数据集方面常常是重要的。分布式技术也能帮助处理海量数据,并且当数据不能集中到一起处理时更是至关重要。


数据挖掘能做什么


1)数据挖掘能做以下六种不同事情(分析方法):

· 分类 (Classification)
· 估值(Estimation)
· 预言(Prediction)
· 相关性分组或关联规则(Affinity grouping or association rules)
· 聚集(Clustering)
· 描述和可视化(Des cription and Visualization)
· 复杂数据类型挖掘(Text, Web ,图形图像,视频,音频等)

2)数据挖掘分类

    以上六种数据挖掘的分析方法可以分为两类:直接数据挖掘;间接数据挖掘

· 直接数据挖掘
    目标是利用可用的数据建立一个模型,这个模型对剩余的数据,对一个特定的变量(可以理解成数据库中表的属性,即列)进行描述。

· 间接数据挖掘
   目标中没有选出某一具体的变量,用模型进行描述;而是在所有的变量中建立起某种关系 。

· 分类、估值、预言属于直接数据挖掘;后三种属于间接数据挖掘

3)各种分析方法的简介

· 分类 (Classification)

    首先从数据中选出已经分好类的训练集,在该训练集上运用数据挖掘分类的技术,建立分类模型,对于没有分类的数据进行分类。
例子:
a. 信用卡申请者,分类为低、中、高风险
b. 分配客户到预先定义的客户分片
注意: 类的个数是确定的,预先定义好的

· 估值(Estimation)

   估值与分类类似,不同之处在于,分类描述的是离散型变量的输出,而估值处理连续值的输出;分类的类别是确定数目的,估值的量是不确定的。
例子:
a. 根据购买模式,估计一个家庭的孩子个数
b. 根据购买模式,估计一个家庭的收入
c. 估计real estate的价值
    一般来说,估值可以作为分类的前一步工作。给定一些输入数据,通过估值,得到未知的连续变量的值,然后,根据预先设定的阈值,进行分类。例如:银行对家庭贷款业务,运用估值,给各个客户记分(Score 0~1)。然后,根据阈值,将贷款级别分类。

· 预言(Prediction)

    通常,预言是通过分类或估值起作用的,也就是说,通过分类或估值得出模型,该模型用于对未知变量的预言。从这种意义上说,预言其实没有必要分为一个单独的类。预言其目的是对未来未知变量的预测,这种预测是需要时间来验证的,即必须经过一定时间后,才知道预言准确性是多少。

· 相关性分组或关联规则(Affinity grouping or association rules)

    决定哪些事情将一起发生。
例子:
a. 超市中客户在购买A的同时,经常会购买B,即A => B(关联规则)
b. 客户在购买A后,隔一段时间,会购买B (序列分析)

· 聚集(Clustering)

    聚集是对记录分组,把相似的记录在一个聚集里。聚集和分类的区别是聚集不依赖于预先定义好的类,不需要训练集。
例子:
a. 一些特定症状的聚集可能预示了一个特定的疾病
b. 租VCD类型不相似的客户聚集,可能暗示成员属于不同的亚文化群
    聚集通常作为数据挖掘的第一步。例如,"哪一种类的促销对客户响应最好?",对于这一 类问题,首先对整个客户做聚集,将客户分组在各自的聚集里,然后对每个不同的聚集,回答问题,可能效果更好。

· 描述和可视化(Des cription and Visualization)
    是对数据挖掘结果的表示方式。


数据挖掘的一般流程
·定义问题:清晰地定义出业务问题,确定数据挖掘的目的。·数据准备:数据准备包括:选择数据--在大型数据库和数据仓库目标中提取数据挖掘的目标数据集;数据预处理--进行数据再加工,包括检查数据的完整性及数据的一致性、去噪声,填补丢失的域,删除无效数据等。
·数据挖掘:根据数据功能的类型和和数据的特点选择相应的算法,在净化和转换过的数据集上进行数据挖掘。
·结果分析:对数据挖掘的结果进行解释和评价,转换成为能够最终被用户理解的知识。
·知识的运用:将分析所得到的知识集成到业务信息系统的组织结构中去。


数据挖掘的商业背景


    数据挖掘首先是需要商业环境中收集了大量的数据,然后要求挖掘的知识是有价值的。有 价值对商业而言,不外乎三种情况:降低开销;提高收入;增加股票价格。

数据挖掘技术实现


    在技术上可以根据它的工作过程分为:数据的抽取、数据的存储和管理、数据的展现等关键技术。

  ·数据的抽取

  数据的抽取是数据进入仓库的入口。由于数据仓库是一个独立的数据环境,它需要通过抽取过程将数据从联机事务处理系统、外部数据源、脱机的数据存储介质中导入数据仓库。数据抽取在技术上主要涉及互连、复制、增量、转换、调度和监控等几个方面的处理。在数据抽取方面,未来的技术发展将集中在系统功能集成化方面,以适应数据仓库本身或数据源的变化,使系统更便于管理和维护。

  ·数据的存储和管理

  数据仓库的组织管理方式决定了它有别于传统数据库的特性,也决定了其对外部数据的表现形式。数据仓库管理所涉及的数据量比传统事务处理大得多,且随时间的推移而快速累积。在数据仓库的数据存储和管理中需要解决的是如何管理大量的数据、如何并行处理大量的数据、如何优化查询等。目前,许多数据库厂家提供的技术解决方案是扩展关系型数据库的功能,将普通关系数据库改造成适合担当数据仓库的服务器。

  ·数据的展现

  在数据展现方面主要的方式有:

  查询:实现预定义查询、动态查询、OLAP查询与决策支持智能查询;报表:产生关系数据表格、复杂表格、OLAP表格、报告以及各种综合报表;可视化:用易于理解的点线图、直方图、饼图、网状图、交互式可视化、动态模拟、计算机动画技术表现复杂数据及其相互关系;统计:进行平均值、最大值、最小值、期望、方差、汇总、排序等各种统计分析;挖掘:利用数据挖掘等方法,从数据中得到关于数据关系和模式的知识。

  

数据挖掘与数据仓库融合发展


  数据挖掘和数据仓库的协同工作,一方面,可以迎合和简化数据挖掘过程中的重要步骤,提高数据挖掘的效率和能力,确保数据挖掘中数据来源的广泛性和完整性。另一方面,数据挖掘技术已经成为数据仓库应用中极为重要和相对独立的方面和工具。

  数据挖掘和数据仓库是融合与互动发展的,其学术研究价值和应用研究前景将是令人振奋的。它是数据挖掘专家、数据仓库技术人员和行业专家共同努力的成果,更是广大渴望从数据库“奴隶”到数据库“主人”转变的企业最终用户的通途。

- 作者: oいばらの泪o 2008年05月7日, 星期三 00:02  回复(0) |  引用(0) 加入博采

高级游戏资源打包技术【转载】
一个大型的商业游戏包含很多资源,如图像、声音、文本、脚本和其他各种类型的数据,为游戏提供一个完整和高效的资源管理系统(包括SDK与编辑器)是游戏引擎开发商必须完成的工作。我们在Numen Game Engine 2.0中实现了一个底层资源打包接口,在接口的基础上实现了纹理编辑器、模型编辑器、单位编辑器和建筑物编辑器等工具,整个系统采用32位的ID来标识资源,具有一级分类的能力,支持资源包的各种常用操作。
    但是在Numen Game Engine 3.0中,我们为了实现一个完美的资源打包系统,完全放弃了以前的所有接口,采用更多新的技术,最终构建了一个功能强大,性能高效的资源管理接口,这篇文章中,我们将从资源编辑器的特性简介、关键技术和资源编辑器功能三个方面,介绍构建一个商业级资源打包系统需要掌握的关键技术和实现细节。

一、特性简介
    Numen Pack Editor 2.0支持以下主要功能特性:
1、创建、打开和关闭资源包。
2、压缩资源包。消除数据添加、修改和删除带来的数据碎片,扩展索引表容量,重设资源包密钥。
3、合并资源包。将外部的资源包整合进当前打开的资源包。
4、释放资源文件。将资源包内的任意文件释放到磁盘。
5、创建文件夹。
6、(批量)添加文件。可以指定文件的独立密钥与压缩选项。
7、从文件夹添加数据(包括文件夹与文件)。可以指定文件的独立密钥与压缩选项。
8、(批量)更新文件。可以选择按列表顺序与按文件名两种方式进行数据更新。
9、(批量)复制、剪切、粘贴、删除和重命名单元。
10、查看和修改资源属性。
    资源编辑器的功能实现主要依托于底层SDK提供的接口,同时,细致周到的用户界面设计和大量方便的组合功能,是编辑器使用层次提高的关键。Numen Pack Editor 2.0在设计中,仅界面的设计就花费了大量时间,期间主要是对各种细节进行反复测试和修改。

二、关键技术
    总的来说,为了确保资源管理系统的高效,需要实现散列表、目录树、存储空间管理、加密/解密和数据压缩五个主要的接口,但是要实现完整的资源系统,还需要其他大量的基础函数,Numen Game Engine 2.0升级到3.0后,只需要实现前三项技术即可完成整个系统的构建。
    (一)散列表
    众所周知,散列表的出现就是为了解决字符串或非简单数据类型(如32位整数)的索引。一般来说,首先将需要索引的数据进行计算,产生一个32位的索引值,好的算法可以使这个索引值分布比较平均,减少产生冲突的可能性;插入操作时,用这个索引值与索引表大小进行模运算,获得它在索引表的位置,如果计算出的位置为空,则直接插入元素,否则将进行冲突处理;查询操作时,先在计算出的第一个索引表位置进行查找,发现元素则返回,否则继续进行查找;删除操作同查询操作,只是找到元素后会给元素打一个删除标记。
    我们有很多的散列算法可用,这里推荐暴雪在MPQ中开发的索引算法,其实该算法最大的好处在于不在散列表中存储要索引的数据,这样在比较操作时就不需要进行长数据的比较,也可以节约存储空间(后面会说到这个只对索引表有直接益处),举例来说:我们要插入一个字符串”e\world\texture\char\tank.png”(长度29字符),如果我们在索引表中存储完整的字符串,最理想的情况下我们也需要比较29个字符长度的数据,如果发生冲突,还将进行更多的比较。
    在MPQ中引入了两个额外的32位索引值来提供比较,这样在任何情况下都不会进行长数据的比较,如上面那个字符串,我们得到索引值dwHash,计算两个参考值dwCheck1和dwCheck2,这样每次元素比较最多只需进行3次32位整数值的数据比较。值得一提的是,这个算法也并不是万能的,在实际应用中,如果我们不需要大量长索引,那么普通算法的劣势将不明显,同时还将节约dwCheck1和dwCheck2的计算时间。
    另一个关键就是如何在索引表中放置冲突元素,一种方法是用链,另一种方法使用顺序,在MPQ中使用的是顺序存储,这样做的好处是实现简单,但是在最坏情况下,查找一个元素可能将遍历一次索引表,但是在正常游戏中,一般不会查询错误的单元,所以这样的情况很少出现。顺便提一下,在将冲突数据进行链的处理时,由于索引表需要存储在文件中,所以这里链需要改造成索引链(如下一个位置是15),而不是采用内存链表。
    (二)目录树
    在资源包中我们对每个单元的全路径进行索引,如e\texture\tank.png,那么在资源管理器中我们不可能通过遍历索引表来构建整个目录树(在1万个以上项目时速度将会明显变慢),而且我们的索引表也不存储任何名称信息。这就需要我们实现一个类似文件树的接口,它将保存所有的目录信息。
    在Numen Game Engine 3.0中,我们用链表实现了目录树,目录树的单元数据结构如下:
struct FILETREEITEM
{
FILETREEITEM* pPrevItem; // 前一个单元
FILETREEITEM* pNextItem; // 后一个单元
FILETREEITEM* pChildItem; // 子单元
FILETREEITEM* pParentItem; // 父单元
DWORD dwHashIndex; // 索引序号
int nNameLength; // 名称长度
WCHAR strItemName[1]; // 单元名称,不包含路径.(可变长度)
};
    采用“上下左右”四个单元指针的目的是为了提高插入的效率和使单元访问更容易,Numen引擎中用了一个小技巧,就是每个单元的第一个子单元(包括根单元),它的pPrevItem指向的是本级最后一个单元,这样做是为了使插入操作能进行后序插入,普通情况下,要实现这个目的,需要提供一个额外的pLastItem指针。
    设计目录树时的难点在于指针的正确处理,如果说单向链表很简单,双向链表并不难,那第一次设计这种属性链表时一定不会一帆风顺的。另外还需要注意一些操作影响的不仅仅是一个单元,还将影响所有的子单元。
    使用可变长度的单元名称将节约大量内存空间。
    为了使各种操作有更多的可定制性,我们还需要在对目录树的各种操作中加入回调函数,如下所示:
// 文件操作参数
#define FILETREEOP_RENAMEITEM 0x00000001 // 重命名单元
#define FILETREEOP_COPYITEM 0x00000002 // 复制单元
#define FILETREEOP_MOVEITEM 0x00000004 // 移动单元
#define FILETREEOP_REMOVEITEM 0x00000008 // 删除单元
#define FILETREEOP_OVERWRITE 0x00000010 // 覆盖操作
#define FILETREEOP_INTERNALCREATE 0x00000020 // 内部创建

// 文件树操作回调函数
// 参数: -strSrcName 源单元名称
//       -strDstName 目标单元名称
//       -dwFlags 文件操作参数,参考FILETREEOP宏定义.
//       -lpUserData 用户自定义数据
// 返回: 0: 执行单元操作
//    其他: 放弃单元操作
typedef LRESULT (CALLBACK *LPCBFILETREEOP)( LPCWSTR strSrcName, LPCWSTR strDstName, DWORD dwFlags, LPVOID lpUserData );
    有了这些回调函数,这样我们就可以非常灵活的实现我们的资源管理器了。
    最后值得一提的是,目录树也是实现采用检验值方式的索引表进行重构的基础,因为没有存储索引信息的索引表,是不可能改变自身大小的,必须通过外部记录的索引信息,将索引表扩容后,进行索引重建。
    (三)存储空间管理
    对操作系统比较熟悉的人都知道,文件系统在长时间使用后会产生大量数据碎片,资源管理器也将面临这个问题。在Numen Game Engine 2.0中,我们只是简单的把任何新增的数据加入到资源包的结尾处,可以定期通过压缩资源包来消除空间浪费。
    在Numen Game Engine 3.0中,我们实现了一个空间管理类,这样任何空间的申请和释放都通过这个类来管理,这个类建立了32个单向链表,每个链表记录一定容量的空闲空间信息,如我们先后释放了4096,89,12589大小的存储空间,然后我们添加大小为70,4000,10000大小的数据,我们将可以申请到重复利用的空间,而不需要增加资源包的大小,同时未用完的空间将被加入到链表中等待分配。
    正是由于存储空间管理器的引入,大大降低了数据的删除和修改操作对资源包大小产生的影响,在配合资源压缩功能,完全不必担心数据碎片带来的空间浪费。
    (四)数据加密/解密
    这个方面的内容可参考的教程和代码较多,算法的强度和效率也各有不同,所以开发商可以根据引擎定位和项目需求进行具体定制。
    资源包中的加密分为文件头加密、索引表加密、目录树加密、数据块信息加密和数据加密,这些加密方式为资源包提供了完整和灵活的保护方案,用户可以根据数据的重要程度和读取效率需求自由定制加密方案。
    (五)数据压缩
    通过提供各种压缩算法,如Huffman,RLE,ZIP,LZW等,为引擎数据提供压缩服务,目前Numen Game Engine 3.0的资源包支持Huffman,RLE和LZW三种压缩算法选择,用户可以自己选择使用他们中的一种或多种对数据进行压缩。

三、资源编辑器功能
    这里将对Numen Pack Editor 2.0中的部分功能进行图文说明:
    (一)压缩数据包
    这里为用户提供了改变索引表大小和资源包加密的机会,资源包索引将会对这个资源包进行重构,花费的时间根据资源包的数据大小,加密强度和压缩等级而定。
    (二)合并资源包
    合并资源包是为了团队配合制作资源而产生,比如美工进行分工后,可以自行制作自己的图形资源,并保存在自己的文件夹中,当资源需要进行整合时,可以统一汇总,而且每个资源包可以保持自己独立的密钥,使团队合作的层次得以体现。
    (三)添加文件
    如果不能批量添加文件到指定文件夹,那添加文件将会变成一件浪费人力的工作,同样我们也需要为一批添加的文件同时指定加密和压缩方案。
    (四)添加文件夹的文件
    这是一个十分重要的功能,当用户有一大批已经制作好的资源需要进行添加时,我们不需要手工建立所有的文件夹,只需要点击几次鼠标,便可将所有资源一次性加入到资源包中。
    (五)更新文件
    如果一个资源编辑器不具备强大和灵活的更新能力,那就不叫资源编辑器了。用户首先选择需要更新的文件,然后选择按序号或者命名更新,就可以一次性完成一批数据的更新操作,而且编辑器提供了更新确认对话框,所以用户不必担心误操作覆盖掉重要的数据。
    (六)文件属性
    如果文件加入资源包后,不能随时查看和编辑它的属性,这将是不可想象的灾难,因为我们根本无法预知未来的需求变化,比如添加时我们希望数据能快速的读取,所以没有给它加入加密和压缩,但是游戏发布后,我们希望保护我们的资源,这是利用文件属性对话框就可以轻易的实现这个目的。
    四、结束语
    Numen Pack Editor 2.0已经比较完善的支持了资源包管理系统应具备的各种功能,而且在用户接口设计上非常注重细节,为用户进行资源处理提供了高效的手段。但是一切技术都是不断发展和完善的,现在的编辑器也需要在更多的项目实践中不断完善和发展,关于Numen Game Engine和Numen Software的更多信息请随时访问www.numenstudio.com进行查询。

由于GameRes发带图片的帖子不方便,要下载程序和图文教程的请访问www.numenstudio.com。
下载地址:http://www.numenstudio.com/media/PackEditor2.0.rar

- 作者: JR 2008年05月6日, 星期二 23:24  回复(1) |  引用(0) 加入博采

Comcast 的老鼠和猫游戏【转】

用BT下魔兽世界客户端,去年还下的顺风顺水呢,今年就下了800多mb就被断网了n次。查了下原因,原来如此啊!

大公司为了挽回败局,往往不择手段。[文/研究员 安替 anti@fawjournal.net]

刚到美国的时候,一个数字让我“哇欧”了一下。家里用的是Comcast 公司的宽带和电视接入,电驴(一种p2p 软件)下载电影每秒达到800 多K,简直和水龙头一样。但很快“哇欧”就变成了恶心——我赶上了“好”时候,Comcast 开始偷偷地限制用户p2p 服务,具体表现就是常常断网,必须重启网络才行。理由是,视频类下载(包括p2p 技术)流量占到总流量的一半以上,不有效管理那么损伤其他用户的权益。我没话可说,因为我总不能向公司抗议他们侵犯了我下载盗版电影的权利。

不过美国网络界就不干了。因为这意味着Comcast 开始甄别用户上网的内容,对特定服务进行限制。往高处讲,就有两个问题:1)违反了网络自由原则,服务商开始干涉用户的合法需求(毕竟美国人不都拿p2p 下载盗版电影的),有了这个先例,那么下面什么违反言论自由的事情都可能做的出来;2)违反了网络中立原则,服务商既提供场地,又参与比赛,而且限制某些特定对手。因为p2p 技术是目前很多网络共享、视频、通话服务的核心技术,这些服务,本身也是comcast的服务内容。这样上纲上线,Comcast 就成为了民主和市场竞争的双重敌人了。

Comcast 抗了几个月,还是迎来了2 月25 日联邦通信管理局(FCC)在哈佛法学院召开的关于宽带网络管理实践的全体委员(En Banc)听证会。听证会由法学院的伯克曼互联网研究中心协办。这个中心一直以推动网络自由和新技术发展为己任,这么安排,委员会的倾向性已经很明显了——这里是支持网络自由一派的主场,另外,哈佛所在的剑桥镇,是麻省第8 选区,旁边的第7 选区,就是众院有关网络中立法案提出者民主党人Edward Markey 的据点!

大公司为了挽回败局,往往不择手段,甚至不怕丢人。最罕见的搞笑事情出现了——堂堂联邦听证会,堂堂哈佛学堂,竟然有一批显然是路人甲、丐帮乙的人在听证会现场酣睡,而还有很多网络公司人士无法进来!媒体最后发现,这些闲杂人等竟然是Comcast 公司雇佣的!在逼问之下,公司发言人只好承认他们的确雇佣无业人员为本地职工占位置,但并没让他们留在里面。

这些近乎下流的招数没用。各代表发言纷纷表示,是否坚持网络中立条款,是关心到美国未来是否继续保持世界领袖地位的头等重要大事。FCC 主席Kevin Martin 在关键发言中提出,他不會吝啬提出强有力的法案,迫使某些大公司遵守网络中立条款。

对于Comcast 关于p2p 技术损害网络主要服务的说法,发言代表也嗤之以鼻。他们问,大家还记得电话时期说那些电话新服务会损害主服务的胡话吗?既然网络视频下载是新趋势,那么网络接入服务商的正确态度是如何发展线路以满足新需求,而不是整天想着怎么压制新对手,以及如何“有效控制”。因为新的希望不是控制出来的,而是竞争出来的。

不过大公司不到黄河心不会死。在国会新法规通过之前,显然Comcast 还会继续我行我素。因为当我昨天下载完新的电视连续剧后,该死的网络又断了一次。

- 作者: JR 2008年05月6日, 星期二 20:47  回复(0) |  引用(0) 加入博采

中国农业大学宿舍楼的震撼一幕!(组图)【转载】
中国农业大学宿舍楼的震撼一幕!(组图)
2008年05月04日23:37:36 [新闻大杂烩]

forex
晚上10点半,中国农业大学奥运场馆偏北方向的近60米高,70米宽的三号学生公寓南侧面,先后展现出用宿舍灯光和彩灯配合搭配拼成的奥运徽上的“京”字、奥运大事时间表、摔跤图、奥运五环、和平鸽、中国地图等21种彩色巨型图案。 Mitbbs.com

画面的切换由各个宿舍开关灯变化形成。Mitbbs.com

农大宿舍楼的震撼一幕! Mitbbs.com

亮灯活动共分为“奥运大事记”、“摔跤动画图案”和“同学心目中的奥运图标”三大板块,通过彩色图案的多幅流动和动态切换,回顾奥运不解之缘。Mitbbs.com

- 作者: 蛮蛮 2008年05月5日, 星期一 23:22  回复(0) |  引用(0) 加入博采

沉睡的雄狮,你终于醒来! 【转载】
沉睡的雄狮,你终于醒来! (2008-04-23 09:58:12)

(如果你现在能看到这篇帖子,那无论你看完后的心情如何,首先是值得高兴的,因为新浪管理员是一个有职业道德的媒体从业者,新浪也是真的在为全世界的华人服务)

 

(至新浪管理员:在这里,本人没有任何反和平的声音,也没有伪造任何事实,本人不是奋青,只是想把一些真相带给更多的中国人,希望你能理解作为处在这非常时期一个中国普通网民的心声,更是一个中国人的心声,希望新浪尽到一个公正媒体的职责,不要删这篇帖子)

 
   考虑了很久,还是决定把这段时间收集的图片发上来,因为都是自己十分不想看到的图片,所以内心很不想把这个东西发在个人blog里,一直关心国家大事时事政治,但并不想过多的言论,毕竟带上政治色彩的任何东西都有点变味。但我觉得作为一个中国人,这次的事情不只是中国政府的的事,人民也该站出来发出点声音了。
 
   介于中国内地现在都在报道西方的反华和藏独势力。我也就开个先河,让大家看看韩国这边民间的真实情况吧。再次重申,政府间的事情我们不管,而是看看民间,还在沉迷韩流的哈韩族们,你们沉住气,我只发一半。看看甚至不知道西藏在哪的韩国民间最近都在干些什么吧。都打出口号必要时候支持政府派军队维护西藏统一的时候,你们哈韩还要去跟安七玄下跪吗?

先看媒体,这张插画似曾相识?是的,这就是韩国的《中央日报》,可以说就是直接把美国报的东西拿过来再报一遍,发生在国外驱赶藏族分子的事说是发生在西藏。

顺便看看高句丽问题时大韩人民的作风吧,东北工程中,因为中国不承认东北以前是韩国的,大韩人民表现出来的团结。但这种团结,是一种病态的团结。

撕咬中国国旗,这让我想到了CNN主播这次对中国“经典“评说中的一个词——野蛮,这种以侮辱他国尊严为代价的爱国情绪我想也只有韩国人能做出来了。其实大家也不用太针对CNN主播了,他能坐上世界超级文明大国美国第一媒体主播的位置,难道没有受过高等教育?他都这样看中国,不敢想象看他新闻那些人眼中的中国是什么样,野人?怪兽?在他们眼中,中国是没有文明的,文明是什么我不知道,但如果就是这些文明国家的文明人士带来的鸦片,血洗圆明园,南京大屠杀诸如此类的文明的话,那我承认,中国没有文明

朝鲜难民问题的时候,让人怀疑这真是礼仪之邦吗?礼到一有问题就把他国的国旗拿来焚烧。国旗是什么,是一个国家的象征和尊严。中国就那么对不起你们吗?你们申请端午节成功的时候,有中国人去烧你们的八卦旗?有人去抵制LG,三星吗?禁止播韩剧了吗?相反的,中国媒体变本加厉的美化韩国,而韩国媒体也在变本加厉地妖魔化中国,在韩国人的眼中,中国人民还在看黑白电视机,民间更是流传着中国人不洗澡的说法,在信息化时代的今天,能把一个拥有960万平方公里国土的邻邦大国长时间妖魔化得这么成功,真的不是一件易事,可见韩国政府和媒体的持之以恒与艰苦奋斗。在我眼中,中国对你们已经仁至义尽了。所谓的在华中小韩企,中方政府给出了多少优惠条件,让你们在这儿建工设厂,为你们提供廉价的劳动力,让你们享受丰富的原材料,而这些企业却拖欠工资集体撤离,这算是回报?

 

这就是韩国小学生的历史书。韩国的主流媒体和民间流传着中国剥夺韩国文化,修改韩国历史的说法,那我们来看看大韩人民受的教育吧,看了这个才知道四川以前也是韩国的,原来我是韩国人。

这似乎有点搞笑,乖乖!原来大韩民国是四大文明古国!

3月18日,也就是3.14过后的第四天,韩国民众再也按捺不住了,集体在中国大使馆门前抗议,要求西藏独立

这让我又想起了白狗村事件,一个韩国普通宠物店

仔细看中间那张照片

放大一看,中国人都知道这张图片是哪里吧,天安门中间毛主席的头像被换成一条白狗,左边写着宠物百货店,右边写着白狗村!这已经不再是单纯的反华了,这是一种极其恶劣的辱华行为,和cnn那位主播的行为的区别是一个放在口里,一个挂在窗外。

 

民间的各种支持藏独活动。

这些受害者的图片的来源不得不让人佩服韩国挖掘图片的本事,连中国人都找不出来的图片居然被韩国人民举着,居然还有举旗的人说西藏在山东下面。近代的中国已经受了那么多的折磨,现在办一个奥运会,你们却唯恐天下不乱,抓着一个西藏问题趁火打劫。难道西藏人民受迫害了不把照片传给同一片土地下的我们是因为我们冷血?难道西藏人民只懂韩语英语法语?受压迫后只把图片传给国外寻求他们的支援?这真得值得我们思考。
 

西方国家还知道找几个国外的藏人带队,可是在韩国漫天的雪山双狮旗下面,却是清一色的韩国人。

不知道韩国人对“屠杀”这个词的理解,西藏大屠杀?

民间的支持藏独演唱会,可见对“人权”的重视。

在这些支持者中,也有很多是韩国基督教徒,关于基督教,本人不想在这儿长篇大论,毕竟一件事物如果同时掺杂了政治和宗教成分,那月亮可以当成太阳。

 

以信件的方式支持藏独

 

藏独支持者们在募集爱心捐献。

藏独支持者们的party

由此可想象,27号的首尔会是个什么样,韩国的藏独网上圣火破坏路线已经出来了,这里就不太方便发了,真的很担忧那天到场的所有为圣火护跑的在韩同胞们,大家得挺住啊!
 
关于韩国的太多我想最了解的是所有在韩国的华人,都知道韩国从来就是报道中国的负面消息,导致了韩国对中国的看法就不用多说了,网上流传着很多留学生的文章,大家可以去找找,大部分是真实的。这次的西藏事件更让韩国人抓住了机会做文章,西藏是中国的?别开玩笑了,在我们的大学课堂里,连香港都是一个国家,更别说西藏和台湾了。曾有韩国同学问我,用汉语的国家除了香港台湾中国新加坡还有哪,我说还有贵国,发明韩文以前。他没说话,表情很奇怪,然后在这学期的韩国历史课上,教授很平静地在坐着200余人左右的大教室缓和地说道“韩国和日本也创造了汉字...这让我再一次的担忧韩国以后的教育。
 
韩国的对华政策友好吗?是的,中韩友好,这是我们国家的腔调,但所有在韩国的华人,你们觉得呢?你们每天在和韩国人接触,每天看韩国网站报纸新闻书籍的你们恐怕该说点话了吧。现在新上任的总统出身在日本,这次中国两会后连日本都发了贺电,唯独韩国不发,新总统上任后就给美国总统通了两个电话,紧跟着制定访美访日行程,提出一个《韩日美共同防御体系》方案,懂点政治的话该知道这是什么意思。再说经济吧,对华的几百亿美元的贸易逆差他们并不尴尬,只进不出的霸王政策还在大喊 made in china get out,一个毒饺子事件都被韩媒轰动成这样你还要什么都买韩版吗?补充一点,现在的韩国总统就是当初改汉城为首尔的汉城市长——李明博。
 
相信喜欢韩国的你曾无数次地受着国内部分以金钱至上的媒体的引导,无数次地为韩剧中的凄美做着一个韩国梦,曾为了一个签名去给韩国人下跪,曾为了见一个韩国明星冒雨等候三小时,曾为了了解所谓的韩国文化成天沉迷在一些八卦周刊上,但这样做后,你们真的了解了韩国?国产的东西就那么不好?希望你们看到这些照片能醒醒,如果真想把这个哈韩族当到底,那么请你全面了解韩国,哈到有血有肉问心无愧哈的有品位有深度,起码对的起养你扶你的国家。
 
我们的政府这次的反映很正确,希望大家不要再怪国家,怪政府了,至于为什么,在这儿不想讨论政治,我想奥运会以后陆续会有人说一些真相出来(其实现在也有些人开始说了,如果你关心资本经济的话可以去看看西方资本近年来的经济情况,会找到一些答案)大家现在需要做的只有四个字:团结一心。
 
最后引用一句话,“经济发展才是硬道理“ 虽然这篇文章的内容让很多人不能接受,但这就是真相,如果你是在韩国的华人,你应该知道我说的是不是事实,韩国要怎么妖魔化中国,那是自己国家的悲哀。希望所有学韩语和在韩国的华人发奋图强,将来战斗在韩中发展的第一战线上,只有我们个体强大了,国家才会强大,才会从根本上改变现状,也只有这样,才称得上真正的哈韩族。
 
(希望大家抓紧时间转载,把这些真相带给你身边的每一个人,本人也不想为难新浪,如果你不是第一次看这篇帖子,那你应该知道这篇帖子的经历,所以请大家注意评论用语,再次希望新浪不要删除,尽到一个公正媒体的职责,在这关键时刻发挥出媒体的积极作用,为全球华人服务) 
你终于觉醒了,沉睡的雄狮!!!

- 作者: JR 2008年05月5日, 星期一 23:20  回复(0) |  引用(0) 加入博采

Castlevenia模仿日志~11:窗口

     把窗口的部分完成了。做了两种,有背景图的和用GDI+画的。有背景的那种采用的是game maker的方法,可以随便拉伸。嘿嘿嘿,有思想一切都不是太难。虽然还没有和人物持有的物品结合起来。不过先贴图留念下把。

5月9日

     把窗口和物品碰撞部分搞定,补完吓。吐血,吐血……追求细节是一个痛苦的过程。
     试了下Gdiplus的渐变画刷,满好用。搭配了下不同的颜色。
   
    偶比较喜欢的颜色,也许就是终版颜色了。

  

   感觉比较正规的颜色。难以取舍啊……

搭配下,这个其实也满好看的。

还作了下状态界面。

累死了……去睡觉了,倒倒……

- 作者: 蛮蛮 2008年05月3日, 星期六 17:24  回复(0) |  引用(0) 加入博采

美国2007 Computer Science Graduate Schools 申请必读 【转载】
 

计算机科学是一门包含各种各样与计算和信息处理相关主题的系统学科,从抽象的算法分析、形式化语法等等,到更具体的主题如编程语言、程序设计、软件和硬件等。作为一门学科,它与数学、计算机程序设计、软件工程和计算机工程有显著的不同,却通常被混淆,尽管这些学科之间存在不同程度的交叉和覆盖。

一、      专业申请形势的介绍及与相关专业的横向比较

11专业录取形势介绍:

CS的申请形势,总体来说是竞争激烈的,甚至可以说用惨烈来形容。由于北美IT行业的回暖转热,IT行业人才需求增幅较大,对于招生方面需求还是很大点。但是由于申请的人数很多,竞争非常激烈,而且来自其他国家的学生的竞争也日趋激烈,比如印度方面的留学生数量增长也非常快。如果从已知06OFFERAD情况(来自中科大bbs)来看,CS录取总数为80,其中有奖(含FELLOWRATA全部)共17,而全奖(fellow,或者同时有fellow+RA,或RA+TA)仅有5个。因此,可以看出CS拿奖的特别是全奖的可能性还是比较低的。

1.2专业下不同二级专业的比较:

     CS专业下分概念方向五个:软件工程、人工智能、理论、系统、软件

    具体的分支专业方向:软件工程 /软件测试 /软件设计;数据库 /数据挖掘;网络应用 /网络协议 / 网络理论 /网站设计;计算机安全 /网络安全;电子商务;分布式计算 /并行计算;操作系统;计算机语言设计;人工智能 /自然语言处理 /知识工程;计算机游戏设计 /图形学 /人机交互 /计算机动画 / 多媒体;算法分析 /计算理论;计算机硬件 /体系结构 /嵌入式设计。

     从申请难易来看,象软件工程、数据挖掘、分布式计算是现在比较热门的专业,录取的人数比较多;而人工智能,计算机理论,算法分析,研究方向偏基础,相对来说申请的人数也会少很多,拿奖学金的机会也会比较大。

1.3CS与其他理工科的专业比较:

与其他理工科相比,CS显然不是那么容易拿奖学金,特别是象生物、物理、化学这样一些专业,拿奖学金比较容易,全奖也比较多。

二、      专业申请中二级专业的分类介绍

2.1计算机专业的二级专业主要有如下几类:

2.1.1 Mathematical foundations 数学基础领域

    数学基础领域主要包括 Boolean algebra(布尔代数)、Discrete mathematics(离散数学)、Graph theory (图形理论)、Mathematical logic (数理逻辑)、Probability and Statistics(概率论和统计学)、Information theory 信息理论)、Domain theory (域论)、Category theory (范畴论)、Set theory (集合论)等方向。

2.1.2 Theoretical computer science 理论计算机科学

理论计算机科学领域主要包括Algorithmic information theory(算法信息理论)、Computability theory(可计算性理论)、Cryptography (密码学)、Formal semantics of programming languages (程序语言的形式语义学)、Theory of computation (or theoretical computer science)   计算理论(理论计算机科学)、Analysis of algorithms and problem complexity (算法和问题复杂性分析)、Logics and meanings of programs(程序逻辑和内涵)、Mathematical logic and Formal languages(数理逻辑和形式语言)、Type theory(类理论)、Quantum computing (昆腾计算)、Quantum information theory(昆腾信息理论)等方向。

2.1.3Hardware 硬件

     硬件领域主要包括Control structures and Microprogramming(控制结构和微程序设计)、Arithmetic and Logic structures(算法和逻辑结构)、Memory structures(存储结构)、Input/output and Data communications(输入/输出和数据通讯)、Logic Design(逻辑设计)、Integrated circuits(集成电路)、VLSI design(超大规模集成电路设计)、Performance and reliability(性能和稳定性)等研究的方向。

2.1.4Computer systems organization 计算机系统组织

     计算机系统组织领域主要包括Computer architecture(计算机体系结构)Computer networks (计算机网络)、Distributed computing(分布式计算)、Performance of systems    (系统性能)、Computer system implementation(计算机系统实现)等方向。

2.1.5 Software 软件

    软件领域主要包括Computer program and Computer programming(计算机程序和计算机程序设计)、Concurrent Programming(并发程序设计)、Parallel Programming(并行程序设计)Program specification(程序规约)、Program verification(程序验证)、Programming techniques(程序设计技术)、Software engineering(软件工程)、Configuration management and Software Configuration Management (SCM) (配置管理和软件配置管理)、Design patterns (模式设计)、Formal methods (形式方法)、Object orientation(面向对象程序设计)、Aspect orientation (面向方面程序设计)、Documentation Optimization(文件优化)、Software metrics(软件度量学)、 Structured programming(结构化程序设计)、Programming languages(程序设计语言)、Imperative programming Languages(命令程序设计语言)、Functional programming Languages 函数程序设计语言)、Logic programming Languages 逻辑程序设计语言)、Operating Systems(操作系统)、Compiler(编译器)、Lexical analysis (语法分析)Compiler optimization(编译器优化)等研究方向。

2.1.6 Data and information systems数据和信息系统

    数据和信息系统领域主要包括如下一些方向:Data structures (数据结构)、Data storage representations(数据储存和表示)、Data encryption(数据加密)、Data compression(数据压缩)、Data recovery(数据恢复)、Coding and Information theory (编码和信息理论)、Files(文件)、File formats(文件格式)、Information systems(信息系统)、Databases (数据库)、Information Storage and retrieval(信息存储和检索)、Information Interfaces and Presentation(信息接口和表述)等。

2.1.7Computing methodologies计算方法论

    计算方法论领域的研究主要有如下几个方向:Symbolic and Algebraic manipulation (符号和代数处理)、Artificial intelligence(人工智能)、Computer graphics(计算机图像学)、Image processing and computer vision(图像处理和计算机视觉)、Pattern recognition(模式识别)、Speech recognition (语音识别)、Simulation and Modeling(仿真和建模)、Document and text processing(文件和文本处理)、Digital signal processing(数字信号处理)等。

2.1.8Computer applications计算机的应用领域

计算机在各领域的应用是非常广泛的,主要有如下这些方面:Enterprise resource planning(企业资源计划)(ERP)、Customer relationship management(客户关系管理)、Human Resource Management Systems(人力资源管理系统)、Numerical analysis(数值分析)、Automated theorem proving(自动定理验证)、Computer algebra systems(计算机代数系统)、Computational chemistry(计算化学)、Computational physics(计算物理学)、     Bioinformatics(生物信息学)、Computational biology(计算生物学)、Medical informatics   (医药信息学)、Computer-aided engineering(半自动计算机工程)、Robotics(机器人技术)、Human-computer interaction(人机交互)、Speech synthesis(言语合成)Telecommunications(电讯学)、Queueing theory(排队理论)等。

2.2从录取难度方面来看:

整体来说,计算机专业的录取难度是比较大的,竞争比较激烈。

象计算机应用、数据和信息系统、计算机硬件和体系结构这样的方向由于应用性较强,毕业后就业情况比较乐观,因此申请的人数也多,竞争比较激烈,又是计算机专业里面录取难度较大的方向。

而象软件,虽然申请人数不少,但是由于招生量比较大,而且涵盖面比较宽,录取难度相对要低一点。

而计算数学、计算方法论这种偏向基础性研究的方向,对数学的要求比较高,申请人数相对少很对,难度也相对低很多。

- 作者: 蛮蛮 2008年05月3日, 星期六 05:29  回复(0) |  引用(0) 加入博采

计算机系毕业生发展方向【转】
 认同作者的大部分观点,值得一读。对于毕业生来说,看见自己未来的方向很有好处,在校生来说,懂得那些课该上,那些课可以逃也很不错:)

      一、关于企业计算方向 
  企业计算(Enterprise Computing)是稍时髦较好听的名词,主要是指企业信息系统如:ERP 软件(企业资源规划)、CRM 软件(客户关系管理)、SCM 软件(供应链管理,即物流软件),银行证券软件财务软件电子商务/政务(包括各种网站),数据仓库,数据挖掘,商务智能等企业信息管理系统。 

  企业计算领域对人才的需求显然永远是数量最大的因为这是计算机应用最多的领域。搞这方面的好处是: 

  (1)人才需求量极大从事企业计算的公司在IT企业中占了大多数。除非在专业上一无特长一般在这一领域总能找到工作。 

  (2)这方面的入门门槛相对较低(如果你的软件功底不是很深可考虑这一领域) 

  (3)这方面的大公司较多大公司要赚大钱所以多将精力花在企业计算业务上.如与正规高校软件学院同学目前实习的CitiCorp、HP、IBM、SAP、NEC等公司都属这一领域的公司。如果将来想到大公司找一份相对稳定的工作,从事这方面机会要大很多。 

  但从事这一领域的缺点也是明显的: 

  由于这方面的入门门槛相对较低,虽然这方面的人才需求量是最大的,但将来竞争对手会较多。您会发现,即使他原不是学IT专业的人,也许他突击几个月后,做得照样像模像样。特别是当您年纪渐大后,您可能会发现,后面的年轻人可能很容易追上你的水平。如果您将来到国外去工作,你可能会发现从事这领域的人更多且高手如云。当然,若您在这一领域经过多年企业经验,达到较高境界(如能设计软件架构),则身价永远是高的。国内在这方面人才领域的主要问题是,有经验的高手太少,皮毛了解的人太多。 

  从事企业计算领域,最重要的技能型技术课程是 

  (1) J2EE架构与程序设计

  (2) 大型数据库系统(如Oracle)

  (3) 基于UML的系统分析与设计。

  如果说还有什么重要的技能,还可将XML与Web Service技术包含进来,若您在这几个领域掌握较好,则不愁找不到工作。其中尤其以J2EE最为重要,目前J2EE已成为企业计算软件开发的最主要平台,也是正规高校软件学院的最重要课程之一。

  尽管该课程只能作为选修课,我们希望正规高校软件学院同学无论将来想从事何种方向,都应学一下J2EE课程,至少可为将来找工作备一手关键功夫。包括想从事嵌入式或其它领域的同学,也是很有必要学一下J2EE的,毕竟J2EE是目前最重要的平台之一,即使您将来不想从事企业计算领域,了解一下J2EE也是必要的,就像一门常识课程一样。

  其它与企业计算关系较密切的技能还包括: Dot Net架构与程序设计、软件测试技术、软件配置管理,该领域较高层次的技能包括数据仓库技术、构件与中间件技术、设计模式等。像通信协议分析与网络程序设计,Unix系统管理等也属有些关系的课程。02级本学期开设的企业计算课程不多,主要是J2EE、Oracle/MSSQL、UML等企业计算领域的最关键技能型技术课程都已学完了。

  您应在空余时间将J2EE,DB、UML等技术再深入地钻研下去,一定要在某个领域有深入的掌握。只是跟着听课,即使学了再多课程也是没用处的,自己钻研下去才是最重要的。只一个J2EE便是博大精深的,足够你啃下去的,钻研下去,您会发现你还要学的相关知识还有很多(包括EJB、XML、Web Service、Design Pattern等)。 

  虽然从事企业计算的人才很多,但以下企业计算领域无论国内外都属稀缺人才: 

  (1) 掌握大型ERP系统,主要是SAP系统,包括SAP Basis(系统管理)或SAP ABAP(编程)或SAP功能模块实施(特别是财务模块FI的实施)。SAP顾问身价是最高的,而且非常难找。其它大型ERP系统,掌握PeopleSoft、Oracle Finacial、J.D.Edward、Siebel等大型ERP软件系统的人也很值钱。这方面的人之所以身价奇高,主要是因为这些软件很专业,特别大,很难有D版可学习,只有特大企业(如世界500强,90以上使用SAP)才用得起,而且必须有实际工作经验才能掌握。如果是一个个人人都很容易有机会接触的软件,那么这方面的人通常就不会稀缺。如果大家将来有机会接触学习这些大型ERP软件系统的机会,建议毫不犹豫地抓住,那将捧上一辈的金饭碗。

  在国外,会SAP的人特别值钱。物以稀为贵,这永远是颠扑不破的真理。SAP的价值不仅是因为他是一个ERP软件, 而是其中体现的现代企业管理理念(如根据订货需求自动安排原料采购和生产计划等)。一般500强公司绝不会像国内很多企业那样,用J2EE从头设计企业的ERP系统(即将是怎样的人力投入,而且设计出来的系统怎么可能是完善的),一定都会使用SAP这样成熟的ERP软件。用不起SAP的公司可能会用J2EE设计ERP系统。 

  (2) 掌握IBM大型机技术的人,如S/390主机,MVS操作系统,JCL作业控制语言,COBOL程序设计语言,DB2关系数据库或IMS层次数据库,CISC中间件交易控制系统等IBM大型机专用技术。国内五大银行,以及国外绝大多数银行的后台系统使用的都是以上平台。IBM大型机号称永不宕机而且平台相对封闭(这样最安全),所以这些要求在24*7环境中连续运行的关键应用(术语叫mission critical applications)都采用IBM大型机。

  这方面的人才之所以稀缺,是因为会大型机的人都是老人(90年代以前搞IT的人),全世界新毕业的IT毕业生不可能再去学IBM大型机(这是一种相对古老的技术)没有新人补上而银行的系统必须维持下去而且银行还要不断开发新业务(如新的存款品种)虽然对IBM大型机人才的绝对需求量不很大但相对恒定银行到哪里找这方面的新人很难找到. 若好找花旗软件也不会花那么大的代价去培训我们的实习同学了(去年培训20多个人听说公司就花了数十万元培训费). 如果您将来到国外找工作会IBM大型机可能是最好找工作的领域之一了而且保证找的都是大银行等好工作我以前教过的计算机专业90-94级的一些同学凡是毕业后从事大型机开发的现多在国外一些很好的公司工作(有几位同学在各国各公司跳来跳去简直如履平地).

  其实我觉得我们最幸福的同学就是在花旗软件做IBM大型机银行软件的同学这样的机会太难得了.正规高校软件学院00级22班一位同学当初放弃保研看准在花旗软件做大型机并且非常努力还未毕业公司便派她到国外参加一个项目的开发成了项目骨干我觉得她当初选择是完全正确的,01级一位女同学刚刚也自愿放弃了保研机会去花旗做大型机,我们祝愿她将来也能有好的前景。其实像花旗软件主动安排并鼓励员工读在职研究生,这样开明的公司目前并不多的,在职读研也是一种不错的选择,又不会失去自己喜欢的实习工作机会,能兼顾)读书的最终目地还是为了工作. 如果您将来在国外找工作根本没人管您是什么文凭国外企业绝不会花冤枉钱只会招有领域工作经验能立即上手的人用最少的钱在限定的时间完成项目. 而在国内因为人力成本较低公司招聘一很多高学历的人才尽管可能根本用不到这么高的学历但国内的人力太便宜了为什么不高消费一下人才呢这样公司的门面还要好看些。 

  (3) 其它如掌握数据仓库技术的人在国内也很少. 目前最主流的数据仓库平台应是ORACLE的数据仓库工具. 在国外会一些特殊数据仓库的人如NCR/TEREDATA的人非常难找. 

  年轻人充满热情喜欢追逐一些热门技术,这当然正确的毕竟学习SAP和大型机的机会毕竟不多毕业时先能找到一份工作是重要的. 但我相信随着年纪的增长大家将来慢慢都会思考的掌握一项竞争对手较少的绝技的重要性将来如果自己到国外工作什么技术最好找工作(对搞软件的人到国外工作或移民是最容易的也许您现在不想但我相信工作多年以后很大一部分同学可能想到国外闯荡一下)你要考虑你今后一生的出路什么样的绝技是最稳定最轻松最高收入的. 搞软件的人当年纪大些时您可能更向住像搞医学人的那样能更多靠经验吃饭而不须整天像年轻人那样不得不去追逐不断出现的软件新技术这个时候也许您也许会发现如果您在SAP或大型机等方面有些绝技您会有很大优势因为这些较偏的领域其技术变化是相对很缓慢的. 

  我还记得在2002年时我曾在业余时间与一位德国人合作面试一些IT人才到德国去那时德方各公司发来的需求有很多是SAP和IBM大型机的我们在众多应聘者中最后也未找到一个在这方面有经验甚至是有一点经验的. 相反掌握流行技术的人因太多而不很值钱. 

  找工作时不仅要盯着国内市场还要有一种放眼全球的眼光,对搞软件的人您将来完全可能到其它国家去工作. 尤其是在欧美、日本、新加坡等国家,对SAP(包括IBM大型机)人才的需求是很大的。毕竟比同学见得多些提醒同学将来多留意有学习这些绝技的机会一旦有机会建议当仁不让. 国内的人才市场可访问www.51job.com,国外的IT人才需求可访问www.hotjobs.com、www.workopolis.com、www.monster.com等著名网站。应经常访问这些网站,以了解市场对人才的具体需求,早做准备。 www.uiok.net

  以上对企业计算领域的观点供大家参考.虽然观点未必正确但确是直言不讳. 总之每个人的脑袋都长在自己脖子上每个人都应有自己的判断. 

  还要注意我以上纯粹是从将来就业的角度谈问题. 如果您将来准备到国外读书则应重视基础课像CAssemblyOOPDiscrete MathData StructureOpeating SystemDatabase PrincipleNetworkSoftware EngineeringCompilerDigital CircuitComputer GraphicsComputer Component and Architecture等基础课在国外大学IT专业中一般都能找到相同课程若国内学过到国外读书时一般可申请免修一部分. 但我也想提醒同学如果您将来毕业时万一申请国外大学不成不得不去找工作时,若只将精力花在这些IT专业学生都会的基础课上(传统IT教育模式) 未掌握一些像J2EE等技能型技术是不容易找到一份工作的我们已有同学有这样的教训。从找工作的角度讲,企业关心的不是您学过什么课程,而是关心您能做什么,有什么技能,能做什么项目。

      二、关于嵌入式系统方向 

  嵌入式系统无疑是当前最热门最有发展前途的IT应用领域之一。嵌入式系统用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常常见到的手机、PDA、电子字典、可视电话、VCD/DVD/MP3 Player、数字相机(DC)、数字摄像机(DV)、U-Disk、机顶盒(Set Top Box)、高清电视(HDTV)、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电刂葡低场⒁搅埔瞧鳌⒑教旌娇丈璞傅鹊榷际堑湫偷那度胧较低场?

  嵌入式系统是软硬结合的东西,搞嵌入式开发的人有两类。 

  一类是学电子工程、通信工程等偏硬件专业出身的人,他们主要是搞硬件设计,有时要开发一些与硬件关系最密切的最底层软件,如BootLoader、Board Support Package(像PC的BIOS一样,往下驱动硬件,往上支持操作系统),最初级的硬件驱动程序等。他们的优势是对硬件原理非常清楚,不足是他们更擅长定义各种硬件接口,但对复杂软件系统往往力不从心(例如嵌入式操作系统原理和复杂应用软件等)。 

  另一类是学软件、计算机专业出身的人,主要从事嵌入式操作系统和应用软件的开发。如果我们学软件的人对硬件原理和接口有较好的掌握,我们完全也可写BSP和硬件驱动程序。嵌入式硬件设计完后,各种功能就全靠软件来实现了,嵌入式设备的增值很大程度上取决于嵌入式软件,这占了嵌入式系统的最主要工作(目前有很多公司将硬件设计包给了专门的硬件公司,稍复杂的硬件都交给台湾或国外公司设计,国内的硬件设计力量很弱,很多嵌入式公司自己只负责开发软件,因为公司都知道,嵌入式产品的差异很大程度在软件上,在软件方面是最有花头可做的),所以我们搞软件的人完全不用担心我们在嵌入式市场上的用武之地,越是智能设备越是复杂系统,软件越起关键作用,而且这是目前的趋势。 

  从事嵌入式软件开发的好处是: 

  (1) 目前国内外这方面的人都很稀缺。一方面,是因为这一领域入门门槛较高,不仅要懂较底层软件(例如操作系统级、驱动程序级软件),对软件专业水平要求较高(嵌入式系统对软件设计的时间和空间效率要求较高),而且必须懂得硬件的工作原理,所以非专业IT人员很难切入这一领域另一方面,是因为这一领域较新,目前发展太快,很多软硬件技术出现时间不长或正在出现(如ARM处理器、嵌入式操作系统、MPEG技术、无线通信协议等),掌握这些新技术的人当然很找。嵌入式人才稀缺,身价自然就高,越有经验价格就越高。其实嵌入式人才稀少根本原因可能是大多数人无条件接触这需要相应的嵌入式开发板和软件另外需要有经验的人进行指导开发流程。 

  (2) 与企业计算等应用软件不同,嵌入式领域人才的工作强度通常低一些(但收入不低)。搞企业应用软件的IT企业,这个用户的系统搞完了,又得去搞下一个用户的,而且每个用户的需求和完成时间都得按客户要求改变,往往疲于奔命,重复劳动。相比而言,搞嵌入式系统的公司,都有自己的产品计划,按自己的节奏行事。所开发的产品通常是通用的,不会因客户的不同而修改。一个产品型号开发完了,往往有较长一段空闲时间(或只是对软件进行一些小修补),有时间进行充电和休整。另外,从事嵌入式软件的每个人工作范围相对狭窄,所涉及的专业技术范围就是那些(ARM、RTOS、MPEG、802.11等),时间长了这些东西会越搞越有经验,卖卖老本,几句指导也够让那些初入道者琢磨半年的。若搞应用软件,可能下一个客户要换成一个完全不同的软件开发平台,那就苦了。 

  (3) 哪天若想创业,搞自已的产品,那么嵌入式是一个不错的主意,这可不像应用软件那样容易被盗版。土木学院有一个叫启明星的公司开发出一个好象叫工程e的掌上PDA,施工技术人员用该PDA可当场进行土木概预算和其它土木计算,据说销路特好。我认识的某大学老师,他开发的饭馆用的点菜PDA(WinCE平台,可无线连网和上网),据他说销路不错,饭馆点点PDA让客户点菜,多显派头档次。当年有一组同学在学Windows程序设计课程时用VC设计了一个功能很强的点菜系统做为课程项目,当时真想建议他们将这个软件做成PDA,估计会有些销路(上海火车站南广场的Macdonald便使用很漂亮的PDA给用户点食品,像摸像样的)。这些PDA的硬件设计一般都是请其它公司给订做(这叫贴牌:OEM),都是通用的硬件,我们只管设计软件就变成自己的产品了。 

  从事嵌入式软件开发的缺点是: 

  (1) 入门起点较高,所用到的技术往往都有一定难度,若软硬件基础不好,特别是操作系统级软件功底不深,则可能不适于此行。 

  (2) 这方面的企业数量要远少于企业计算类企业。特别是从事嵌入式的小企业数量较多(小企业要搞自己的产品创业),知名大公司较少(搞嵌入式的大公司主要有Intel、Motorola、TI、Philip、Samsung、Sony、Futjtum、Bell-Alcatel、意法半导体、Microtek、研华、华为、中兴通信、上广电等制造类企业)。这些企业的习惯思维方式是到电子、通信等偏硬专业找人。由于正规高校软件学院以前毕业生以企业计算为主,所以正规高校软件学院与这些企业联系相对较少。正规高校软件学院正积极努力,目前已与其中部分公司建立了联系,争取今后能有正规高校软件学院同学到这些企业中实习或就业。 

  (3) 有少数公司经常要硕士以上的人搞嵌入式,主要是基于嵌入式的难度。但大多数公司也并无此要求,只要有经验即可。 

  正规高校软件学院同学若学习嵌入式,显然应偏重于嵌入式软件,特别是嵌入式操作系统方面,应是我们的强项。对于搞嵌入式软件的人,最重要的技术显然是(实际上很多公司的招聘广告上就是这样写的): 

  (1) 掌握主流嵌入式微处理器的结构与原理 

  (2) 必须掌握一个嵌入式操作系统 

  (3) 必须熟悉嵌入式软件开发流程并至少做过一个嵌入式软件项目。 

  正规高校软件学院在嵌入式软件方面最重要的课程包括: 

  (1) 嵌入式微处理器结构与应用:这是一门嵌入式硬件基础课程,正规高校软件学院用这门课取代了传统的微机原理与接口课程(目前国内已有少部分高校IT专业这样做了,因为讲x86微机原理与接口很难找到实际用处,只为教学而已)。我们说过,嵌入式是软硬件结合的技术,搞嵌入式软件的人应对ARM处理器工作原理和接口技术有充分了解,包括ARM的汇编指令系统。

  若不了解处理器原理,怎么能控制硬件工作,怎么能写出节省内存又运行高速的最优代码(嵌入式软件设计特别讲究时空效率),怎么能写出驱动程序(驱动程序都是与硬件打交道的)很多公司招聘嵌入式软件人员时都要求熟悉ARM处理器,将来若同学到公司中从事嵌入式软件开发,公司都会给你一本该设备的硬件规格说明书 (xxx Specification),您必须能看懂其中的内存分布和端口使用等最基本的说明(就像x86汇编一样),否则怎么设计软件。有些同学觉得嵌入式处理器课程较枯燥,这主要是硬件课程都较抽象的原因,等我们的嵌入式实验室10月份建好后,您做了一些实验后就会觉得看得见摸得着。还有同学对ARM汇编不感兴趣,以为嵌入式开发用C语言就足够了。其实不应仅是将汇编语言当成一个程序设计语言,学汇编主要是为了掌握处理器工作原理的。一个不熟悉汇编语言的人,怎么能在该处理器写出最优的C语言代码。

  在嵌入式开发的一些关键部分,有时还必须写汇编,如Bootloader等(可能还包括BSP)。特别是在对速度有极高要求的场合(如DSP处理器的高速图像采集和图像解压缩),目前主要还要靠汇编写程序(我看到过很多公司是这样做的)。当您在一个嵌入式公司工作时,在查看描述原理的手册时,可能很多都是用汇编描述的(我就遇到过),这是因为很多硬件设计人员只会写或者喜欢用汇编描述,此时您就必须看懂汇编程序,否则软硬件人员可能就无法交流。很多嵌入式职位招聘时都要求熟悉汇编。 

  (2) 嵌入式操作系统类课程 

  除了WinCE的实时性稍差外,大多数嵌入式操作系统的实时性都很强所以也可称为实时操作系统Real Time Operating System.从事嵌入式的人至少须掌握一个嵌入式操作系统(当然掌握两个更好)这在嵌入式的所有技术中是最为关键的了。目前最重要的RTOS主要包括: 

  第一类、传统的经典RTOS:最主要的便是 Vxworks 操作系统,以及其Tornado开发平台。Vxworks因出现稍早,实时性很强(据说可在1ms内响应外部事件请求),并且内核可极微(据说最小可8K),可靠性较高等,所以在北美,Vxworks占据了嵌入式系统的多半疆山。特别是在通信设备等实时性要求较高的系统中,几乎非Vxworks莫属。Vxworks的很多概念和技术都和Linux很类似,主要是C语言开发。像Bell-alcatel、Lucent、华为等通信企业在开发产品时,Vxworks用得很多。但Vxworks因价格很高,所以一些小公司或小产品中往往用不起。目前很多公司都在往嵌入式Linux转(听说华为目前正在这样转)。但无论如何,Vxworks在一段长时间内仍是不可动摇的。与Vxworks类似的稍有名的实时操作系统还有pSOS、QNX、Nucleus等RTOS。 

  第二类、嵌入式 Linux 操作系统:Linux的前途除作为服务器操作系统外,最成功的便是在嵌入式领域的应用,原因当然是免费、开源、支持软件多、呼拥者众,这样嵌入式产品成本会低。Linux本身不是一个为嵌入式设计的操作系统,不是微内核的,并且实时性不强。目前应用在嵌入式领域的Linux系统主要有两类:一类是专为嵌入式设计的已被裁减过的Linux系统,最常用的是uClinux(不带MMU功能),目前占较大应用份额,可在ARM7上跑另一类是跑在ARM 9上的,一般是将Linux 2.4.18内核移植在其上,可使用更多的Linux功能(当然uClinux更可跑在ARM 9上)。

  很多人预测,嵌入式Linux预计将占嵌入式操作系统的50以上份额,非常重要。缺点是熟悉Linux的人太少,开发难度稍大。另外,目前我们能发现很多教材和很多大学都以ucOS/II为教学用实时操作系统,这主要是由于ucOS/II较简单,且开源,非常适合入门者学习实时操作系统原理,但由于ucOS/II功能有限,实用用得较少,所以正规高校软件学院不将其作为教学重点,要学习就应学直接实用的,比如 uClinux就很实用。况且熟悉了Linux开发,不仅在嵌入式领域有用,对开发Linux应用软件,对加深操作系统的认识也有帮助,可谓一举多得。据我所知,目前Intel、Philip都在大搞ARMLINUX的嵌入式开发,Fujitum则是在自己的处理器上大搞Linux开发。目前在嵌入式Linux领域,以下几个方面的人特别难找,一是能将Linux移植到某个新型号的开发版上二是能写Linux驱动程序的人三是熟悉Linux内核裁减和优化的人。正规高校软件学院在该嵌入式Linux方面的课程系列是:本科生操作系统必修课,然后是Linux程序设计选修课,最后是嵌入式Linux系统选修课。正规高校软件学院在Linux方面目前已有较强力量,魏老师和张老师熟悉Linux开发,金老师和唐老师熟悉Linux系统管理。 

  第三类、 Windows CE 嵌入式操作系统:Microsoft也看准了嵌入式的巨大市场,MS永远是最厉害的,WinCE出来只有几年时间,但目前已占据了很大市场份额,特别是在PDA、手机、显示仪表等界面要求较高或者要求快速开发的场合,WinCE目前已很流行(据说有一家卖工控机的公司板子卖得太好,以至来不及为客户裁减WinCE)。WinCE目前主要为4.2版(.NET),开发平台主要为WinCE Platform Builder,有时也用EVC环境开发一些较上层的应用,由于WinCE开发都是大家熟悉的VC环境,所以正规高校软件学院学过Windows程序设计课程的同学都不会有多大难度,这也是WinCE容易被人们接受的原因,开发环境方便快速,微软的强大技术支持,WinCE开发难度远低于嵌入式Linux。

  对于急于完成,不想拿嵌入式Linux冒险的开发场合,WinCE是最合适了(找嵌入式Linux的人可没那么好找的),毕竟公司不能像学生学习那样试试看,保证开发成功更重要。根据不同的侧重点 ,WinCE还有两个特殊版本,一个是MS PocketPC操作系统专用于PDA上(掌上电脑),另一个是MS SmartPhone操作系统用于智能手机上(带PDA功能的手机),两者也都属于WinCE平台。

  在PDA和手机市场上,除WinCE外,著名的PDA嵌入式操作系统还有Palm OS(因出现很早,很有名)、Symbian 等,但在WinCE的强劲冲击下,Palm和Symbian来日还能有多长正规高校软件学院可能是全国高校中唯一一家开设专门的Windows CE嵌入式操作系统课程的学校,这主要是基于以下原因:正规高校软件学院本身前面便有Windows程序设计课程,同学学过VC后再学WinCE非常方便自然,通过学习WinCE同样也可了解嵌入式软件的一般开发过程,对Linux有惧怕心理的同学也很合适。

  很显然,嵌入式Linux永远不可能替代WinCE,而且将来谁占份额大还很难讲,毕竟很多人更愿意接受MS的平台,就像各国政府都在大力推LINUX已好长时间,但您能看到几个在PC机上真正使用LINUX的用户据我观察目前在嵌入式平台上LINUX是叫得最响但还是WinCE实际用得更多.嵌入式LINUX可能更多地是一些有长远产品计划的公司为降低成本而进行长远考虑 二是微软亚洲研究院对正规高校软件学院WinCE课程的支持计划,我们也很希望将来正规高校软件学院能有同学通过微软的面试去实习。WinCE和多媒体(如MPEG技术)是微软亚洲工程院目前做得较多的项目领域之一他们很需要精通WinCE的人。 

  总结关于嵌入式操作系统类课程,若您觉得自己功底较深且能钻研下去,则可去学嵌入式Linux若您觉得自己VC功底较好且想短平快地学嵌入式开发,则正规高校软件学院的WinCE课程是最好的选择。 

  (3) 嵌入式开发的其它相关软件课程 

  搞嵌入式若能熟悉嵌入式应用的一些主要领域,这样的人更受企业欢迎。主要的相关领域包括: 

  A、数字图像压缩技术:这是嵌入式最重要最热门的应用领域之一,主要是应掌握MPEG编解码算法和技术,如DVD、MP3、PDA、高精电视、机顶盒等都涉及MPEG高速解码问题。为此,正规高校软件学院已预订了一位能开设数字图像处理课程的博士。 

  B、通信协议及编程技术:这包括传统的TCP/IP协议和热门的无线通信协议。首先,大多数嵌入式设备都要连入局域网或Internet,所以首先应掌握TCP/IP协议及其编程,这是需首要掌握的基本技术其次,无线通信是目前的大趋势,所以掌握无线通信协议及编程也是是很重要的。无结通信协议包括无线局域网通信协议802.11系列,Bluetooth,以及移动通信(如GPRS、GSM、CDMA等)。 

  C、网络与信息安全技术:如加密技术,数字证书CA等。正规高校软件学院有这方面的选修课。 

  D、DSP技术:DSP是Digital Signal Process数字信号处理的意思,DSP处理器通过硬件实现数字信号处理算法,如高速数据采集、压缩、解压缩、通信等。数字信号处理是电子、通信等硬件专业的课程,对于搞软件的人若能了解一下最好。目前DSP人才较缺。如果有信号与系统、数字信号处理等课程基础,对于学习MPEG编解码原理会有很大帮助。 

  (4) 嵌入式开发的相关硬件基础 

  对于软件工程专业的学生,从事嵌入式软件开发,像数字电路、计算机组成原理、嵌入式微处理器结构等硬件课程是较重要的。另外,汇编语言、C/C、数据结构和算法、特别是操作系统等软件基础课也是十分重要的。我们的主要目地是能看懂硬件工作原理,但重点应是在嵌入式软件,特别操作系统级软件,那将是我们的优势。 

  我们的研究生里有些是学电子、通信类专业过来的,有较好的模拟电路和单片机基础,学嵌入式非常合适。嵌入式本身就是从单片机发展过来的,只是单片机不带OS,而现在很多嵌入式应用越来越复杂,以至不得不引入嵌入式操作系统。另外,为追求更高速的信号处理速度,现在在一些速度要求较高的场合,有不少公司是将一些DSP算法,如MPEG压缩解压缩算法等用硬件来实现,这就涉及到HDL数字电路设计技术及其FPGA/IP核实现技术,这方面的人目前市场上也很缺。 

  (5) 题外话 

  另外,能写驱动程序的人目前是非常紧缺的(驱动程序也可归于嵌入式范畴),包括桌面Windows中的DDK开发环境和WDM驱动程序。公司每时每刻都要推出新产品,每一个新产品出来了,要能被操作系统所使用,是必须写驱动程序的。写驱动程序就必须掌握操作系统(如Windows或Linux)的内部工作原理,还涉及到少量硬件知识,难度较大,所以这方面的人很难找。想成为高手的同学,也可从驱动程序方面获得突破。

  我可说一下自己的经历,三年前我曾短暂地在一家公司写过WinCE驱动程序(正是因为知道这方面的人紧缺,所以才要做这方面的事),尽管那以前从未做过驱动程序,应聘那个职位时正是看准了公司是很难招聘到这方面的人,既然都找不到人,驱动还得有人做,这正是可能有机会切入这一领域的大好机会。面试时大讲自己写过多少万行汇编程序,对计算机工作原理如何清楚,简历中又写着我曾阅读完两本关于Windows Driver Model的两本英文原版书,写过几个小型的驱动程序练习程序(其实根本没写过,我们的同学将来千万不要像我这样,早练就些过硬功夫,就不至于沦落到我这等地步,就不用像我那样去欺骗公司了,我这是一个典型的反面教材),居然一切都PASS(当然最重要的是笔试和面试问题还说得过去),这只能说明这一领域找人的困难程度。公司本就未指望找到搞过驱动的人,找个有相关基础的人就算不错了。做了以后,发现也并不是怎样难的。其实搞驱动程序的工作是很舒服的,搞完一个版本就会空一段时间,只有等公司新的芯片推出或新的OS出现后,才需要再去开发新一版驱动,那时有将近一个月时间空闲着在等WinCE .NET Beta版推出,准备将驱动程序升级到CE .NET上,现在在软件学院工作整日忙,无限怀念那段悠闲时光。 

  很巧合,最近本人无意中再次体会到了嵌入式的迷人之处。上周我那用了3年的手机终于不能WORK了。此次更新,除要求有手机常见功能外,最好有MP3功能(现在很多英语听力都有MP3文件),最好有英汉词典,最好还能读WORD文档。最后选了个满足以上条件的最便宜的手机DOPOD 515(斩了我2.2K,但想想这也算自己对嵌入式事业的支持,这样便也想开了),算得上最低档的智能手机了。回来一查,手机的about显示,本手机Processor是ARM,其OS是MS Smartphone(即WinCE .NET 4.2),这么巧合,简直可做为学习嵌入式课程的产品案例了(等我们的WinCE课程开得有声有色后,希望能从微软研究院搞些Smartphone来开发开发)。有OS的手机果然了得,金山词霸、WORD、EXCEL、REGEDIT等居然都有smartphone版的,PC上的MP3、DOC等居然在download时都可被自动转换成smartphone格式,真是爽。完全可用Windows CE自己开发一些需要的程序download到自己的手机上。现在市面销售PDA智能手机火爆,MS总是财源滚滚。但我已发现国产的ARMLINUX手机出现在市面上,价格只1.2K。 

  在GOOGLE网上能搜索太多的关于嵌入式系统的讨论了,我刚发现一个http:www.embyte.com 非常不错,有很多有经验者谈自己的体会投入到其中的论坛中,你会切身感到嵌入式学习的热潮。 

  要么走ARMWinCE,要么走ARMLINUX,要么走ARMVXWORKS。每个搞嵌入式的人都可选一条路,条条大路通罗马。

      三、关于游戏软件方向 

  将游戏软件人才称为数字媒体软件人才可能更好听些,包括游戏软件策划(最缺游戏策划的人)、游戏软件美术设计、游戏软件程序设计等多方面的人才,对软件学院,游戏软件程序设计当然是最合适的了。 

  游戏软件人才的确目前很缺,听说很多游戏软件公司苦于没新人才补充,特别是没有高手补充,不得不相互挖人才,以至将游戏软件人才身价越抬越高。网上说日本教育部刚刚批准成立了日本第一家专门培养四年制游戏软件人才的本科大学。其实国内很多大学,特别是软件学院都有搞游戏软件人才的设想,但目前很少有做成的,主要原因是找不到能上游戏软件课的教师,听说有个学校只能花很大的价钱从Korea找老师来上课,果真缺到此等地步 

  已有很多青少年沉湎于网游而颓废的实例,好在还不至于上升到制造精神鸦片的高度,所以开发游戏软件的人也不必每日惭悔(但开发儿童益智类游戏软件的人是不需惭悔的),如果想想这是为发展民族软件产业做贡献,那反倒是一件有意义的事情了。不过听一家游戏软件公司的老板讲,搞游戏软件开发是非常辛苦的。 

  若想自己创业,搞搞游戏软件是不错的主意。现在网上网站或公司都在收购游戏软件(特别是手机游戏软件,因为手机游戏用户可选从网站上download到手机上,不像网游那么复杂),按download次数分成或一次性收购的都有。我们的同学在校期间是否也可发点小财搞得好,说不定可卖到国外网站,直接挣$$$呢。 

  大致游戏分成以下几类: 

  (1) PC类游戏,包括单机和网游。这类游戏开发平台基本上都是基于VC和DitrectX(如DirectShow,DirectDraw,D3D等,DirectX资料可直接到MS网站上查)。DirectX和OpenGL是两个主要的图形标准,OpenGL跨平台(Unix/Windows上都可跑),尽管很多搞研究的人对OpenGL赞不绝口,将DirectX骂得一文不值,但事实是,在Windows平台上,DirectX是最快最方便的,所以在Windows平台上的游戏还是DirectX当家。 

  (2) 手机游戏:目前手机游戏主要开发平台有两类: 

  第一类手机游戏是 J2ME 平台(Java 2 Micro Edition),J2ME本是为嵌入式平台设计的Java,但由于Java生来就需要Java虚拟机(JVM)来解释,所以在嵌入式产品很少用J2ME(太慢太耗内存)。但在手机游戏中J2ME倒有用武之地,我想这可能主要是Java可跨OS平台的原因,因为手机的OS是千奇百怪的。我对J2ME完全外行,但上次听Square Enix 公司的人说,J2ME与我们同学学过的J2EE还是有较大差别的。据我所知,目前手机中用的较多的是KJava语言,KJava是运行在一种叫K Java Virtual Machine的解释器上(K JVM是SUN早期为演示J2ME在嵌入式系统应用而开发的一个虚拟机),所以将在K JVM上运行的J2ME叫KJava。尽管SUN说今后不保证支持K JVM,将开发新的更高性能的J2ME虚拟机取而代之,但由于KJava出现较早,很多早期的手机游戏软件都将K JVM假想成J2ME虚拟机的标准了,所以目前有大量的KJava手机游戏软件存在,而且还在用KJava继续开发。特别是日本的手机游戏软件由于开发较早(像叫什么docomi的日本最大的电信运营商手机游戏搞得很火),多是基于KJava的。所以目前市场上在招聘手机游戏软件人才时,很多要求掌握KJava。有关J2ME请到Sun的网站上找资料。 

  另一类手机游戏是 BREW 平台,BREW是美国高通公司(Qualcomm,CDMA核心技术都是该公司开发的,有无数移动通信技术专利)发明的,据说可编译成二进制代码,那当然快了。主要的开发语言是C/C。但迫于被指责为较封闭的压力,目前Qualcomm已推出BREW平台上的J2ME虚拟机(但可想像那将是怎样慢的速度)。Qualcomm搞定了很多手机制造商签定BREW授权许可协议,最狠的是Qualcomm与中国联通绑在一起大堆基于BREW的手机游戏,所以有些公司招聘时要求掌握BREW也就不奇怪了。 

  去年00级22班毕业答辩时,有一位同学讲的是在公司做的KJava游戏(那是一家日本游戏软件公司),还一位同学讲的是另一家公司做的BREW游戏,看来不同的公司有不同的选择。将来谁会更火,我估计随着手机硬件资源的不断提高,不会在乎一个JVM的开销,J2ME应更有前途,毕竟它是更开放的。 

  (3) 专用游戏机:如电视游戏,XBOX,PS2等。 

  从著名游戏公司发来的对网游和手机游戏的人才需求,很有代表性。从中我们可看出,游戏公司对人才的需求主要是以下技术: 

  (1) 计算机图形学,特别是3D编程与算法,包括DirectX 或 OpenGL。开发平台是 VC/DIRECTX 或 KJAVA。 

  (2) 公司说,手机游戏因手机资源有限,必须对图像进行压缩,所以若有一些图像压缩算法知识比较好。像若能有MPEG压缩算法较好,手机上采用的是比MPEG压缩得更狠的一些特殊算法,但触类旁通。 

  (3) TCP/IP Socket编程是搞网游开发的人必须掌握的。 

  (4) 人工智能知识:复杂游戏可能需要一些AI算法。 

  (5) 网络与信息安全知识: 网游要防外挂。 

  一般游戏公司的网游服务器是基于 Linux 平台的,所以还提出了对游戏服务器端软件工程师的技术需求(精通MSSQL、ORACLE、MYSQL等数据库,精通Linux Programming,特别是Socket编程)。还有对维护游戏、网站人才需求(ASP.NET和数据库)。注意一条,最好有自己的游戏软件作品,若您应聘时能带一个 DirectX 作品,那将有多强的竞争力,所以最重要的是现在就要行动,实践,实践,再实践。

- 作者: JR 2008年05月3日, 星期六 05:07  回复(0) |  引用(0) 加入博采