http://blog.sina.com.cn/allenyxb[订阅][手机订阅]
个人资料
评论
读取中...
访客
读取中...
博文

场景管理之消息发送

    好久没有写东西出来和大家共同揣摩,真是对不住大家了。现在终于腾了一些时间来继续和大家研究网络游戏制作技术,在这一节中,我就要向大家介绍网络游戏服务器中World场景划分和场景中消息分发问题。

    在前面我基本向大家讲述的都是一些基本的技术问题,从某种意义上讲。属于纯技术范畴的东西,但现在要向大家讲的,应该是属于服务器功能设计范畴的。在这里,我未必讲的很好,有遗漏之处就请大家谅解和指正。

    对于有一定游戏服务器开发基础的朋友而言,应该都明白一个网络游戏服务器和客户端之间的一个基本关系: 玩家客户端是游戏服务器一个局部COPY表现。这个说法听起来可能有一些绕口,简单的解释下也就是说:客户端所具备的区域信息也就是游戏服务器相同区域数据的一份COPY,而表现的意思,也就是说,CLIENT端将这样的数据信息图形化,并且通过屏幕来进行显示,从而来呈现出一个多姿多彩的游戏世界。这样说大家应该能够听懂了吧?再不懂的话,就自己琢磨了。

    说了上面那么多,大家一定要问“SERVER

最近因为自己主持的项目出现些问题,太忙了,所以好久都没有继续写东西和大家进行探讨制作开发部分了。在这一节中就要向大家介绍另外一个重要的部分,并且也是最头疼的部分:线程同步和数据保护。

  关于线程的概念我在前面的章节中已经介绍过了,也就在这里不累赘—“重复再重复”了。有一定线程基础的人都知道,线程只要创建后就如同脱缰的野马,对于这样的一匹野马我们怎么来进行控制和处理呢?简单的说,我们没有办法进行控制。因为我们更本就没有办法知道CPU什么时候来执行他们,执行他们的次序又是什么?

  有人要问没有办法控制那我们如何是好呢?这个问题也正是我这里要向大家进行解释和说明的,虽然我们不能够控制他们的运行,但我们可以做一些手脚来达到我们自己的意志。

  这里我们的做手脚也就是对线程进行同步,关于同步的概念大家在《操作系统》中应该都看过吧!不了解的话,我简单说说:读和写的关系(我读书的时候,请你不要在书上乱写,否则我就没有办法继续阅读了。)

处理有两种:用户方式内核方式
用户方式的线程同步由于有好几种:原子访问,关键代码段
续上在这里我将要向大家简单介绍一下游戏服务器中必须要处理另外一项主要技术:
  内存分配处理技术也可以称为内存池处理技术(这个比较洋气,前面通俗的好,呵呵)

  开始向大家介绍一般情况下我们对于内存的一些基本操作。简单而言,内存操作就只有三个步骤:申请、使用、销毁。而对于这些操作我们在C和C++中的处理方式略有不同:

在C中我们一般用malloc(….)函数来进行申请,而对应销毁已经申请的内存使用free(…)函数。
在C++我们一般使用new操作符和delete操作符进行处理申请和销毁。
大家一定要问了,我们一般都是这样处理的呀!!没有什么可以说的哦!!呵呵,我感觉就有还是有一些东东和大家聊的哦。先聊简单几条吧!!

1.Malloc(…..)和free(….), new ….和 delete …必须成对出现不可以混杂哦,混杂的话,后果就不可以想了哦!!(也没有什么,就是内存被泄漏了,呵呵)

2.在我们使用new …和delete ….一定要注意一些细节,否则后果同上哦!!什么细节呢?下面看一个简单的例子:
char *block_memory = NULL;
block_memory = new char[1024];

续上在这里我将要向大家简单介绍一下游戏服务器中必须要处理另外一项主要技术:

线程池技术

   开始 我来向大家简单来介绍一下线程池的概念,先简单了解下线程先,线程可以理解为一个function , 是一个为了进行某一项任务或者处理某一项具体事务的函数。例如:

UINT WINAPI FunctionCtrl(void *) //线程处理函数
{
     进行某一项任务或者处理某一项具体事务
     …………
     return EXITFUNCTION_CODE; //退出码
}

   而我们的线程池自身可以理解为是很多线程的一个管理者也可以说是一个很多线程的统筹者。因为我们的线程池具有生成线程功能也具有撤消线程的权利。这就是简单的线程池的概念(我的理解,呵呵!!)接下来就来具体介绍线程池了!!

   首先 介绍我们为什么要使用线程池技术呢?大家都知道我们的游戏服务器端要处理大量的用户请求,,同时需要发送大量的游戏数据到客户端,从而来驱动客户端程序的执行和维持游戏的进行。那我们的服务器端是如何进行处理的呢?其

续上在上面我简单的说了一下服务器完成端口处理部分,接下来我想大家介绍一下关于如何建立服务器和客户端的联系规则,也就是服务器和客户端的游戏协议部分。有不足之处希望大家和我进行交流。

   首先解释一下这里协议的概念,协议大家都了解是一种通信规则,例如:TCP/IP,UDP等等,这些是我们在网络通信过程中所处理使用的协议。而我们这里的协议是我们的游戏服务器和客户端的通信规则。简而言之,也就是客户端发送到服务器的数据包和服务器发送的数据包双方解释规则。下面就通过几个部分来具体介绍这种协议的建立和处理。

消息头定义

   如果我们能够解释双方的数据包的意义,我们就必须为双方数据包定义一个统一规则的消息头,我是这么定义消息头的。服务器数据包和客户端数据包分别定义不同的消息头。以下就是双方消息头的简单定义。

struct ServerMsg_Head //服务器消息头
{
WORD s_version; //版本信息
BYTE s_flages; //消息标志
BYTE s_who; //消息驱动者
BYTE s_sort; //消息类别
BYTE s_value; //消息值
WORD s_len; //消息长度
} ;
    当今网络游戏在中国大陆已经在大范围的蔓延,暂且不论这样的一种趋势会带来什么样的游戏产业趋势。这里只就网络游戏的制作和大家进行交流,同时将自己的制作经验写处理,希望为中国的游戏业的发展做出一点点的贡献。。

网络游戏的程序开发从某种意义上来看,最重要的应该在于游戏服务器端的设计和制作。对于服务器端的制作。将分为以下几个模块进行:

1.网络通信模块
2.协议模块
3.线程池模块
4.内存管理模块
5.游戏规则处理模块
6.后台游戏仿真世界模块。

现在就网络中的通信模块处理谈一下自己的看法!!

在网络游戏客户端和服务器端进行交互的双向I/O模型中分别有以下几种模型:
1. Select模型
2. 事件驱动模型
3. 消息驱动模型
4. 重叠模型
5. 完成端口重叠模型。

  在这样的几种模型中,能够通过硬件性能的提高而提高软件性能,并且能够同时处理成千上百个I/O请求的模型。服务器端应该采用的最佳模型是:完成端口模型。然而在众多的模型之中完成端口的处理是最复杂的,而它的复杂之处就在于多服务器工作线程并行处理客户端的I/O请求和理

简单游戏结构示例(2)(2009-11-24 01:55)

 

// MemoryMag.h

#ifndef __MEMORY_MAG_H__
#define __MEMORY_MAG_H__

#include <stdio.h>
#include <assert.h>

template <class T>
class CMemoryMag
{
public:
    CMemoryMag(int size);
    ~CMemoryMag();

    T *GetNew();
    int Free(T *var);

private:

    T *m_data;
    int *m_freed;
    int m_freedSize;
    int m_maxSize;
    int m_curSize;
};

template<class T>
CMemoryMag<T>::CMemoryMag(int size) :
m_maxSize(size),
m_curSize(0),
m_freedSize(0)
{
    m_data = new T[size];
    assert(m_data != NULL);

    m_freed = new int[size];
    assert(m_freed != NULL);
}

templat

简单游戏结构示例!(2009-11-24 01:49)

    突然很想整理一下自己所学到的东西,加深自己对游戏结构的深入了解。就像修房子一样,别管你用多贵的砖头,它只是一块砖头而已,并不是你想要的房子。砖头可以在开发的时候随时换,但是结构一旦定下来,就不好修改了。

那么一个基本,却又efficient的结构究竟是什么样的呢?很简单。所有你所需要的就是引擎,无限状态机和内存池。这三个东西一点都不复杂,你可以从头开始写:
首先是你的引擎类,需要些什么呢?
class CEngine
{
public:
    CEngine();
    ~CEngine();

    int Initialize();
    int Start();
    int Restart();
    int Pause();
    int Shutdown();

    int AddModule(CModuleBase *newModule, int moduleID, int updateFrequency);

    int RemoveModule(int moduleID);

};
这就是一个引擎需要具备的基本功能,不要管图形,也不要管网络,什么都不要管。只是负责加入一个

非常感谢大家对上一篇文章的支持,在大家的支持下,我决定推出浅谈网络游戏开发(2)这篇文章。
 

首先,再次强调一下,网络游戏开发极为困难,技术含量相当的高,其编程知识涉及网络编程,操作系统进程、线程编程,图形图像编程(DirectX / OpenGL),WIN32 API编程(Windows下开发),以及各种算法和数据结构,同时对设计人员策划能力要求也颇高,如不能构思出一个吸引玩家的游戏世界,也必将导致开发失败
 

目前,国内的网络游戏市场被韩国游戏霸占,情形让人心寒。在国内网络游戏编程资源奇缺的环境下,我希望把自己的一些经验和想法说出来,供大家参考,起一个抛砖引玉的作用。
 

对于我在浅(1)中提出的架构,如果大家有更好的修改建议,欢迎大家共同探讨修改,把我国的网络游戏开发水品提高到世界级标准。最起码,也要在国内市场是立足!
 

好了,费话就不多说了,正文开始。
 

 本游戏服务器端操作系统采用UNIX,因为UNIX是标准的服务器操作系统,可保证网络游戏的稳定性。因此,以下所有的编程都将针对UNIX进行。
  服务器端的整体构架如下:通讯模块,消息传递模块,游戏规则模块,线程管理模块,游戏世界管理模块。
 
通讯模块:
  通讯模块主要实现与客户端的通讯功能,实际上,通讯模块就是对套结字Socket的封装。Socket是UNIX下的网络通讯基础,对于一个Socket我们可以对其进行读写操作,读入的数据来自客户端,写入的数据可供客户端读取。
  Socket主要有阻塞套接字和无阻塞套接字两种,对于无阻塞套结字,每次读写后,不管读写的字节数是否达到要求,都立即返回;而对于阻塞套结字,若读写字节数不够,函数将被阻塞,直到所有待处理的数据都处理完毕才返回。可以看出,若采用无阻塞套结字,则将使网络传输变得很不稳定,在网络环境不好时很难控制传输。因此,对于我们的系统,将采用阻塞模式。
  我们下一个面临的问题是怎么知道何时读入,如果在不合适的时候从阻塞套接字读入数据,那线程很可能将被阻塞,这里采用了select——多路复用技术,原理是对我们的socket进行