人一生这一辈子,能记住多少事?还是写下来的好。 注册 | 登陆
浏览模式: 标准 | 列表全部文章

【转】Online-game服务器端设计(3)

  下面我想来谈谈关于服务器上NPC的设计以及NPC智能等一些方面涉及到的问题。首先,我们需要知道什么是NPC,NPC需要做什么。NPC的全称是(Non-Player Character),很显然,他是一个character,但不是玩家,那么从这点上可以知道,NPC的某些行为是和玩家类似的,他可以行走,可以战斗,可以呼吸(这点将在后面的NPC智能里面提到),另外一点和玩家物件不同的是,NPC可以复生(即NPC被打死以后在一定时间内可以重新出来)。其实还有最重要的一点,就是玩家物件的所有决策都是玩家做出来的,而NPC的决策则是由计算机做出来的,所以在对NPC做何种决策的时候,需要所谓的NPC智能来进行决策。

» 阅读全文

Tags: 网络游戏, 服务器

【转】Online-game服务器端设计(1、2)

  谈这个话题之前,首先要让大家知道,什么是服务器。在网络游戏中,服务器所扮演的角色是同步,广播和服务器主动的一些行为,比如说天气,NPC AI之类的,之所以现在的很多网络游戏服务器都需要负担一些游戏逻辑上的运算是因为为了防止客户端的作弊行为。了解到这一点,那么本系列的文章将分为两部分来谈谈网络游戏服务器的设计,一部分是讲如何做好服务器的网络连接,同步,广播以及NPC的设置,另一部分则将着重谈谈哪些逻辑放在服务器比较合适,并且用什么样的结构来安排这些逻辑。

» 阅读全文

Tags: 网络游戏, 服务器

【转】C/C++的思索 C++之父访谈录

作者:佚名
翻译整理:pigprince
----------------------------------------------------------------------
在1998年的元旦,Bjarne Stroustrup(C++之父)接受了IEEE《计算机》杂志记者的专
访。编辑很自然的认为他会对于过去七年来使用他创建的语言进行面对对象设计做一个
历史性的回顾。而在这个专访中,记者获得了更有价值的新闻,但是最后编辑决定为了
整个IT产业,这个稿子不能发表,但是就像其它被砍掉的新闻,往往还是弄得路人皆知
的。
这一篇适当时专访的完全拷贝,没有被编辑、删改或者做过什么润色处理,也没有发布
过,可能看起来不像常见的杂志文章,但这是实情。
你会发现真正引人入胜的地方... ...

» 阅读全文

【转】c调用c++和c++调用c时所使用的extern "c"的区别

使用extern "C" 主要是因为C编译器编译函数时不带参数的类型信息,只包含函数的符号名字。如
int foo( float x )
C编译器会将此函数编译成类似_foo的符号,C连接器只要找到了调用函数的符号,就认为连接成功。
而C++编译器为了实现函数重载,会在编译时带上函数的参数信息。如它可以把上面的函数编译成类似于_foo_float这样的符号。
所以,C调用C++,使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。
如:

C++代码
  1. // C++ Code   
  2. extern "C" int foo( int x );   
  3. int foo( int x )   
  4. {   
  5.    //...   
  6. }  


这样,编译器会将foo函数编译成类似_foo符号,而不会编译成类似_foo_int符号
则C可以这样调用C++函数

C++代码
  1. // C Code   
  2. int foo( int x );   
  3. void cc( int x )   
  4. {   
  5.     foo( x );   
  6.     //...   
  7. }   

如果想调用重载的C++函数,则须封装单独的接口共C调用。

C++代码
  1. // C++ Code   
  2. void foo( int x );   
  3. void foo( float x );   
  4.   
  5. extern "C" void foo_i( int x )   
  6. {   
  7.     foo( x );   
  8. }   
  9. extern "C" void foo_f( float x )   
  10. {   
  11.     foo( x );   
  12. }   

则C中可这样调用

C++代码
  1. // C Code   
  2. void foo_i( int x );   
  3. void foo_f( float x );   
  4. void ccc( int x1, float x2 )   
  5. {   
  6.     foo_i( x1 );   
  7.     foo_f( x2 );   
  8.     // ...   
  9. }    


而C++调用C,extern "C" 的作用是:让C++连接器找调用函数的符号时采用C的方式 如:

C++代码
  1. // C Code   
  2. void foo( int x );   


C++这样调用C函数

C++代码
  1. // C++ Code   
  2. extern "C" void foo( int x );   


就是让C++连接器能过类似于_foo来查找此函数,而非类似于_foo_int这样的符号。

Tags: c++, c

【转】网游服务端结构设计

LoginServer <-----> GameServer

服务端主体分为LoginServerGameServer, LoginServer做帐户认证, GameServer做游戏主逻辑,

中间也可以加一个CharServer, 做人物管理, 新建删除人物之类的, 也可以并到GameServer

, LoginServerCharServer都比较简单, 略过.

通过LoginServer的验证后将分配给Client一个SessionID, 然后与GameServerCharServer的通信,

都以此SessionID为认证码. Client只有发送正确的SessionID才能与GameServer建立连接.

 

2.GameServer层次结构

GameServer分为三层, 网络层<--->逻辑处理层<--->数据库层

每层都有一个消息处理队列, 存放待处理的消息. 消息队列可以采用先进先出队列的方式, 也可以

采用堆或者优先队列的方式, 按优先级对待处理消息进行简单的排序, 嘿嘿, 是不是有点类似QoS

的思想.

每层采用线程池技术, 预先建立一定数量的空闲线程,  不够时建立新线程, 过多时则销毁线程,

保证线程池中有指定数量的空闲线程(Min/Max), 主线程不断检查处理队列是否有待处理消息,

有则从线程池中分配一空闲线程处理之.

偶在Linux下线程池是用pthread_cond_waitpthread_cond_signal实现的.

 

2.1.网络层

本层根据操作系统不同可以有多种实现, 主要功能是与客户端建立TCP连接, TCP流分割成一个个封包,

如果有加密就解密, 如果有压缩就解压缩, 加入事务层的处理队列, 同时把处理队列中待发送的消息发

送出去, 如果要加密就加密, 如果要压缩就压缩.

Windows下采用IOCP模型, Unix-like系统下可采用select/poll(epoll)/kqueue

偶在偶的服务端中采用了select方式, Linux单个端口的连接数有限制, 所以偶开了多个线程监听一组端口,

LoginServer做负载均衡, 从而保证不会出现某个端口连接数过多的情况. 每当有新客户端要登录时,

LoginServer判断每个端口的连接数量, 选最小发送给客户端. 偶想这里也可以做成动态方式,

当每个端口平均连接数超过XXXX, 就开新线程监听新端口, 并通知LoginServer.

 

2.2.逻辑处理层

本层是GameServer的核心.

根据操作码(OPcode)把消息分配到每个子模块里面处理. 最简单的方法就是用从0开始的连续的OPcode, 建立

一个与Opcode对应的处理函数的数组, Opcode作为数组的下标, 这样只需要O(1)的时间就可以调用到所需的函数

Hash都省了, 又简单又高效.

子模块详见第7部分

 

2.3.数据库层

本层用于数据存储, 本质上就是把内存里的数据存到硬盘上, 要是你够拽的话, 可以不用现有的数据库,

自己写算法存储文本文件, 但为了方便起见, 也为了提高效率, 还是用数据库比较好.

windows下用MSSQL, 或者用MYSQL,

Unix-like系统下可以用的就多了, 能多兼容几种数据库最好

MYSQL的性能优异, 功能上稍差一点, 如果不需要用到存储过程的话, MYSQL还是首选的.

数据库层一般用单线程已经足够, 可以不需要做对象互斥, 编程方面也会简单一点. 但是需要注意的是,

数据库操作方面一定要用Transaction, 可以有效防止复制现象发生, 比如:交易操作一旦发生错误,

rollback到交易之前, 不会发生钱已交出, 东西却没拿到的情况.

 

3.消息格式定义

3.1.网络层<-->逻辑层消息格式(网络封包格式)

3.2.逻辑层<-->数据库层消息格式

 

4.游戏对象定义(Object)

object

  |-------> item

  |           |----> container(容器类对象,如仓库、背包等)

  |

  |-------> unit

  |           |-----> player

  |           |-----> monster

  |           |-----> npc

  |           |-----> corpse(尸体对象)

  |

  |-------> gameobj

              |-----> dynamicobj(如技能产生的临时对象)

 

5.地图场景管理

6.脚本系统

7.逻辑层模块化设计  

 

对于地图场景管理打算采用这种方式

在服务器上把场景划分为小区域(视野大小)。每个区域对应一个list,场景中的所有对象按他们的位置加入到对应区域的list,那么每次行走只需要把消息发送给几个相临区域的Player

 

一个建议:

可以把GameServer的网络层剥离出来做成一个应用级网关(Application-level Gateway),因为这部分虽然逻辑简单但消耗资源确是比较大的。做成单独的可以使你的系统伸缩性更好,GameServerGate可以是1:N

 

 

对于一个分布式服务器架构来说要考虑的问题就很多:

首先要有一套设计良好的应用服务器框架和通讯中间件,应用服务器是上层应用的重要基础设施,用来实现诸如服务定位、名字注册、负载平衡、服务集群、故障重起、时间服务、LOG服务等等功能,通讯中间件也是不能少的,如果服务器之间通讯用手工写socket通讯的话,那很快你就会被协议处理、各种微妙的时序、同步等问题所困扰。可以说,你的服务器架构能实现到多复杂能堆多高,关键就看这两样实现的有多坚固耐用。

其次对象状态的序列化很重要,这关系到对象同步、对象persistent、状态迁移、故障恢复等等诸多问题。问题远不是把对象状态写到一个流里就完事那么简单的,做好这一块那就等于解决了一半的服务器逻辑问题了。

然后再谈谈分布的问题,基本上有两种思路,一种是按逻辑功能划分计算资源,一种是按容量划分计算资源。按逻辑功能划分是比较容易想到一种方式,简单的说就是将不同的功能模块实现到不同的进程里,这种方案看似不错,实则问题多多。首先是各模块之间必然要进行交互,这样就会引起很多细粒度的远过程通讯,一来造成性能损失二来增加了实现难度,其次是各模块负载并不均衡,很容易产生性能瓶颈,也很难实现负载平衡,另外这样的服务器程序调式起来将是一场噩梦。当然,凡事都没有绝对,一切设计都要根据实际情况来决定,有时候该按功能划分的还是要按功能划分,比如小高建议的划分一个应用级网关出来在某些情况下就很有效。现在已有的一些我们所能见到的超大无缝连接世界的分布式实现,其基本的思想是将世界划分成一系列相连的块,为每个块分配计算资源来实现并行分布运算。关键的问题在于处理相临块边界之间的同步问题,如果处理不好就可能造成同步失调、物品复制等等BUG,这需要一个设计良好的同步算法。关于计算资源的分配我们也 可以有两种选择,一种是使用性能强劲的多CPU服务器,在单进程里用多线程并行计算,即所谓的SMP架构,这样的优点是简单、高效,缺点是成本高,伸缩性不高。另一个就是服务器集群架构了,这样实现起来更复杂、而且服务器的瓶颈大多出在I/O而非计算上,使用集群以后增大了服务器之间的通讯量,设计不好反而造成性能损失,不过优点也很明显,降低成本,提高伸缩性,通过良好的设计还能实现故障恢复(也就是集群中任何一台服务器当机都不会影响游戏的运行)

最后再谈谈游戏逻辑的处理,一种设计是让服务器处于被动状态,只有客户请求到达再进行逻辑处理,刷新对象状态,这样可以降低一些计算量,但是因为服务器不进行对象状态的模拟,缺乏一些必要的信息,会限制一些功能(特别是真三维世界运动)的实现。我现在更倾向于传统游戏的做法,让服务器运行一个游戏逻辑循环,定时的模拟对象状态。

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bisword/archive/2009/02/03/3859667.aspx

【转】一种经典的网络游戏服务器架构

这个图是一个区的架构图,所有区的架构是一样的。上面虚线框的ServerGroup和旁边方框内的架构一样。图上的所有x N的服务器,都是多台一起的。红线,绿线,和蓝线图上也有图示,这里就不多介绍了。关于Agent Server大家也能看出来,其实就是Gate。
这里主要介绍下图上的标记了号码的位置的数据连接的内容和意义。

» 阅读全文

Tags: 网络游戏, 服务器, 架构

用PHP实现的反向代理程序。

今天闲着无聊,写了这么一个小程序。不过本人没条件测试,所以最终效果还不知道。哈哈。

具体的设置是需要设置rewrite所有链接到代理程序的文件上,然后就可以通过此程序访问其它站点了。不过估计性能不会太高吧。反向代理还是用NGINX来做好些吧。不过对于虚拟主机倒是有用武之地了。

代码如下:

» 阅读全文

epoll 事件的检测


1.。。

epoll 事件中发现
就EPOLLIN , EPOLLOUT , EPOLLPRI可以用.

EPOLLERR 和 EPOLLHUP什么情况下才能监测出这种问题啊.

我的内核是2.6.20
可是用EPOLLRDHUP的时候编译包错.
RecvMessThread.cpp:48: error: ‘EPOLLRDHUP’ was not declared in this scope

» 阅读全文

Tags: epoll, 事件检测

Records:20512345678910»