几年前Pomelo刚出来的时候,关注了一段时间,那时候文档完全没有,只有鼓吹Pomelo各种牛逼特性的博文,而且那些鼓吹的特性让我也觉得如果我自己来从头再来再造一个轮子的话,也不可能造的比之更好了.于是我信了.文档嘛,相信面包总是会有的.但是在当时,还没有真正能够用到实战和工作的业务场景,所以一直搁置到现在.
如今在软件行业也算混了这些年,总想着要玩出一个自己的作品来,就当自己30岁的礼物.想了很久,给自己做一个移动端的游戏甚好.
做游戏,客户端优先选自己熟悉的Android了, 至于服务端,花了一个通宵找了各种资源,然并卵,没有找到合适的开源的框架,最终还是回归柚子怀抱,虽然现在文档差不多很齐全了,但是万事开头难.对于各种概念的不理解,职责不明确,搞的一头雾水.不过本着极客的精神,终于还是成功迈开了脚步,这个系列的笔记,就当给那些希望从0-1的小白们做参考了.
废话不多说,这一篇的任务就搭建一个完整的HelloWorld通信环境.实现的目标是在Android客户端发送一条文本后,收到服务器发来的响应.
第一步: 服务器端环境搭建:
pomelo服务端环境推荐在linux环境上,因为各种资源,以及依赖的下载过程,在linux shell里边执行起来神快. 于是我选择的系统是Ubuntu14. 当然我的个人电脑本身就是此系统(纯属个人爱好,对window系统已经完全不爱了.).
具体的安装过程参考官方:https://github.com/NetEase/pomelo/wiki/Home-in-Chinese
对于各种神奇的概念,我选择无视了,我们不需要去理解那些前端/后端,rpc之类的概念,我坚信水到自然成.
按照教程上的HelloWorld 运行game-server. 然后 再开一个shell,并运行node app. 最终可以在浏览器中看到一个成功的网页.说明我们的服务器端环境OK了.
HelloWorld的客户端是js. 而我们想要的客户端是android. 于是在网上搜索各种pomelo与android的资源,最终找到 pomelo用于android的库:
https://github.com/NetEase/pomelo-androidclient
下载后,就是两个jar包. 丢进libs目录下即可直接使用.
第二步:在Android客户端开发.
1. 新建Android HelloWorld APP. 并在手机上成功运行(这一步非常重要,如果HelloWorld都没有成功运行,说明我们的开发环境是有问题的,不要等到我们代码都写了不知几何的时候,才发现环境错了.)
2. 将我们刚才下载的两个包:socketio.jar和 pomelo-android-client.jar放入libs目录,并添加为lib.
3. 很显然我们是要开发网络相关APP,所以权限一定不要忘掉.
4. 编写一个全局的App类,代码如下:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
_client = new PomeloClient("192.168.1.31", 3010);
_client.init();
}
private static PomeloClient _client;
public static PomeloClient getClient() {
return _client;
}
}
- 以上代码大家应该 看的出来,我是想共享出一个全局的PomeloClient对象,两个参数分别是服务器端的IP地址,以及端口号.因为我的手机和电脑在局域网环境下,所以IP只需要局域网IP即可.端口号需要查看服务端game-server目录下的server.json中的配置.
- 在MainActivity中编写一个简单的按钮点击后发送消息的逻辑:
@OnClick({R.id.sendBtn})
public void onClick(View view) {
switch (view.getId()) {
case R.id.sendBtn: {
sendMsg("HelloWorld");
break;
}
}
}
private void sendMsg(String msg) {
JSONObject msgObj = new JSONObject();
try {
msgObj.put("msg", msg);
} catch (JSONException e) {
e.printStackTrace();
}
App.getClient().request("connector.entryHandler.hello", msgObj, new DataCallBack() {
@Override
public void responseData(JSONObject jsonObject) {
System.out.println(jsonObject.toString());
}
});
}
- 这里边我觉得最难理解的位置就是router参数.为什么要写成”connector.entryHandler.hello”,以及系统如何能够找到正确的请求处理业务等等.
- 其实在我看来,这个router更像是我们平常写的接口名称.只不过这里的接口名称分成了几个层次, connector/ entryHandler/ hello.
而这几个层次又分别代表什么呢?
我们在服务器端可以看到如下的目录结构:
-app
--servers
---connector
----handler
------entryHandler.js
而在entryHandler.js中我们又可以看到:
Handler.prototype.hello = function(msg, session, next) {
next(null, {code: 200, msg: 'game server is ok.'});
};
由此我们可以简单的得出结论:
handler是我们某一类具体业务的处理层.比如专门处理用户 登录注册,忘记密码等业务的handler. 比如专门处理聊天的Handler.
而handler.js中的每一个属于比如:hello.就是某一个具体功能的入口.
我们可以自己实现很多业务模块的Handler.js 然后 在其中实现此模块的所有业务逻辑.
而APP端的访问方式则就是以这样一个层级路径定义的”路由”.
最后一步:
当上面代码都写完以后,先要运行game-server .才能启动APP.
运行game-server.只需要在shell终端cd到game-server目录并执行pomelo start即可.
然后 运行APP,点击发送按钮,查看我们的日志:
01-12 18:54:26.150 5665-5693/cn.andrewlu.app.pomelo I/org.netease.pomelo: pomeloclient is connected.
01-12 18:54:51.220 5665-5693/cn.andrewlu.app.pomelo I/io.socket: < 2::
01-12 18:54:51.220 5665-5693/cn.andrewlu.app.pomelo I/io.socket: > 2::
01-12 18:54:52.100 5665-5665/cn.andrewlu.app.pomelo I/io.socket: > 3:::������connector.entryHandler.hello{"timestamp":1452596092104,"msg":"HelloWorld"}
01-12 18:54:52.125 5665-5693/cn.andrewlu.app.pomelo I/io.socket: < 3:::{"id":1,"body":{"code":200,"msg":"game server is ok."}}
01-12 18:55:16.410 5665-5693/cn.andrewlu.app.pomelo I/io.socket: < 2::
01-12 18:55:16.410 5665-5693/cn.andrewlu.app.pomelo I/io.socket: > 2::
01-12 18:55:41.550 5665-5693/cn.andrewlu.app.pomelo I/io.socket: < 2::
01-12 18:55:41.550 5665-5693/cn.andrewlu.app.pomelo I/io.socket: > 2::
从以上日志可以看出,客户端连接成功,并发送了一条消息,消息响应为:game server is ok.
同时,每隔25秒左右客户端会收到一个2:: 的心跳包,然后 立即回复一个同样的心跳包,否则服务器端会认为客户端已断开连接.
写在结尾:
当我退出APP时,发现日志仍然在继续打印,心跳包依旧没有停止.说明socket连接并没有断开.这也是我们需要注意的地方,除非程序退出时明确调用 disconnect(),否则程序其实并没有真正退出.
这对于省电要求较高的APP来说是必须要考虑的.
下一篇将继续pomelo-android的研究,在搞清楚完整的工作流程后,我将开始着手自己的小众游戏开发.