前言
游戏开发中最复杂的模块,没有之一。其实我也不想写这篇文章,怎奈框架代码卖出去了,得给我的用户一个交代。
网络模块都需要实现哪些功能呢?按我以往的开发经验总结如下:
- 消息的正常发送与接收
- 长链接的断线重连
- 消息发送失败与尝试
- 长链接的心跳处理
- 适应各种服务器定义的协议格式
- 适应各种数据传输格式
- 屏蔽长短链接的差异
- 长链接支持发送协议号与接收协议号不同的情况。
- 让短链接也可以像长链接一样更新数据。
有必要屏蔽长短链接吗?
这个看需求吧
有没有开发过程中将长链接改成短链接的情况呢?你客户端不支持,服务器可是支持的。
如果一个团队有很多开发人员,作为主程的你是否要屏蔽底层逻辑,提供统一的调用接口给其他开发人员使用呢?
如果你一个人做一款游戏,你就随便来吧,随便什么样的方式只要你开心就好。
类图
- Service 实现ServiceInterface接口负责屏蔽链接类型
- Message 负责封装发送和接收的消息。
- MessageHander 负责编解码处理。
- ServiceInfo 保存服务器信息。例如 ip 端口,协议号映射等信息。
- RemoteProxy 负责调用Service发送消息,接收Service返回的消息并通过事件派发给监听者。
关键代码
- ServiceInfo
- ServiceInterface
- Service
- MessageHandler
- Message
- RemoteProxy
如何使用呢?
- 定义一个类来处理链接的监听
- 定义一个地址和开发环境相关的数据类
- 实现编解码处理类
- 定义协议号常量类
- 定义一个链接
- 使用方式
export default class LoginController extends LogicController {
constructor(){
super(LoginProxy.instance());
}
private static ins:LoginController;
static instance():LoginController{
if(!this.ins){
this.ins = new LoginController();
}
return this.ins;
}
//注册协议号与回调函数
getProtoList(){
return [
[NetConfig.OPEN,this.netOpen],
[LoginProtocolIDs.LOGIN,this.loginRsp],
];
}
netOpen(){
cc.log(' 链接成功 ')
this.pushView('Prefab/LoginView','LoginView',null,ModuleManager.getLoader(),UIIndex.STACK)
}
//进入模块 先链接服务 当然也可以先弹出界面,再推送链接结果。
intoLayer(){
ModuleManager.setModuleID(ModuleID.LOGIN)
//进入此模块,先进行链接操作,如果链接成功 会走loginRsp 函数
this.remoteProxy.connect(new ServiceInfo(NetConfig.HTTP,AddressConfig.getAdress(AddressConfig.LOGIN,0)));
}
// 点击登陆按钮发送请求。
loginReq(name:string){
cc.log(" loginReq ",name);
this.sendMessage(LoginProtocolIDs.LOGIN,{name:name,channel:'crazy'});
}
//登陆成功
loginRsp(msg:ReceiveMessage){
cc.log(" loginRsp msg ",msg);
//由于服务器已经关闭,所以不会被调用,正常内容返回时会走这里。
}
}
结语
细节代码太多了,如果都粘贴上来无法忍受。其实网络那些事论坛里已经有人说的很详细了。使用方式也很多,就好像都是用xxgl,每个引擎实现的方式都不同。我只是从框架和封装的角度整理一下具体的使用方式,其实细节的东西,你没有遇到的时候也是没办法理解的,代码里都是经验。有想法的同学留言吧。