最近在研究网络游戏开发,感觉结构很好玩,所以就将自己学到了解到的记录下来。博客前几篇的Socket通信讲的就是网络游戏部分Socket的基本结构。上一篇的对MySql使用就是服务器对数据库的连接使用。今天要介绍的就是游戏服务器的设计架构以及一些核心代码。
通常,网络游戏开发需要跟服务器交互的模块是登陆,注册,创建房间,进入房间,开始游戏,位置同步,动画同步等等等等。我们在开发之前需要设定我们的开发模式以及开发协议。比如在登陆时,我们不光要发送我们输入的用户名和密码,还要发送我们设定的请求模块和响应模块。即RequestCode和ActionCode。这样,我们在客户端这面每次发送数据格式为:
数据头(4字节)+RequestCode(枚举类型,4字节)+ActionCode(枚举类型,4字节)+data(未知字节)
这样我们在服务端就要对我们的数据进行对应的解析了。在服务端我们规定通过RequestCode来寻找对应处理的Controller模块。处理完我们在将数据返回的数据+ActionCode返回给客户端,客户端在根据ActionCode寻找对应的Controller来处理服务器发送回来的响应。
如Socket通信那篇讲的我们用创建Server类来创建一个服务端,然后在创建一个Client类来分别管理连接进来的客户端,这样对客户端的管理会非常直观。我们在客户端通过Message类对接收到的数据进行解析。会得到如下格式的三个数据:RequestCode,ActionCode,String。然后我们使用回调函数将数据传入我们用于专门处理请求响应的函数。嗯,这时候我们的另一个管理类脚本就要诞生了。就是ControllerManager。ControllerManager是用于对所有Controller模块进行管理。下面是我们部分代码可以直观了解下:
首先我们需要创建BaseController,让之后的Controller继承自BaseController,这样方便ControllerManager来统一管理。
abstract class BaseController
{
protected RequestCode requestCode=RequestCode.None;
public RequestCode RequestCode { get { return requestCode; } }
public virtual string DefaultHandle(string data,Client client,Server server){return null;}
}
接下来我们创建一个UserController来处理对于登陆,注册等用户信息相关的请求。
class UserController:BaseController
{
public UserController()
{
requestCode=RequestCode.User;//设置requestCode为User 这样所有发送User相关的请求都会在这个类里处理
}
//这里要保证函数名和我们的actionCode名字一样 这样才能找到对应的处理函数
public string Login(string data,Client client,Server server)
{
}
}
下面是我认为很重要的ControllerManager代码:
class ControllerManager
{
private Server server;
private Dictionary controllerDic=new Dictionary();
public ControllerManager(Server server)
{
this.server = server;
InitController();
}
private void InitController()
{
DefaultController defaultController=new DefaultController();
controllerDic.Add(defaultController.RequestCode,defaultController);
UserController userController=new UserController();
controllerDic.Add(userController.RequestCode,userController);//将创建的controller添加到字典里进行管理
}
//根据requestcode来寻找对应Controller 然后在通过ActionCode来寻找controller里对应的函数来处理
public void HandleRequest(RequestCode requestCode,ActionCode actionCode,string data,Client client)
{
BaseController controller;
bool IsGet = controllerDic.TryGetValue(requestCode, out controller);
if (IsGet == false)
{
Console.WriteLine("没有找到对应的RequestCode"); return;
}
string methodName = Enum.GetName(typeof (ActionCode), actionCode);//获取actionCode的名字
MethodInfo mi = controller.GetType().GetMethod(methodName);//根据actionCode名字寻找controller里对应的函数方法
if (mi == null)
{
Console.WriteLine("没有找到对应的方法");
return;
}
object[] parameters=new object[] {data,client,server};//将需要传进去的数据打包起来
object o = mi.Invoke(controller, parameters);
if (o == null || string.IsNullOrEmpty(o as string)) return;
Console.WriteLine(o as string);
server.SendResponse(client,actionCode,o as string);//将返回来的数据信息和actioncode一起通过client类发送回客户端
}
}
而对于数据库的连接,我们在client里实现。在controller类里我们可以通过参数client来很方便的实现对数据库的数据的调用获取。以上是服务端的设计架构。感觉很清晰,很好用。
如果本博客对你有帮助,记得点关注哦!