本文旨在梳理 pomelo 服务端与 cocos-js 客户端之间的通讯流程。为了简化演示,我们直接使用 pomelo 官方 demo(聊天室)作为服务端代码。

pomelo 官方 demo 聊天室默认支持浏览器客户端,接下来我们在此基础上加入 cocos-js 客户端的实现,使 cocos 与浏览器版本能够互通。

环境准备

  1. 安装 Node.js
  2. 下载聊天室 websocket 版本:https://github.com/NetEase/chatofpomelo-websocket
  3. 参考聊天室官方说明:https://github.com/NetEase/pomelo/wiki/chat
  4. 下载 cocos-js pomelo API:https://github.com/NetEase/pomelo-cocos2d-js,其中 pomelo-cocos2d-js.js 是 pomelo 的 cocos-js 运行库

启动服务端

新建 start.bat,输入以下内容:

cd game-server
                start pomelo start  // game_server
                cd ..
                cd web-server // web server
                start  node app.js

启动成功后效果如下:

打开浏览器,访问 127.0.0.1:3001,启动两个浏览器客户端进行测试。

开发 cocos 客户端

新建 client.js,封装 pomelo 的连接与通讯逻辑:

require("pomeloClient.js");// 引入pomelo api
                //全局单例instance
                client = {};
                
                function Client() {
                
                    username = "cocos-js";
                
                    this.onChat = null;
                    this.onAdd = null;
                    this.onLeave = null;
                    this.onDisconnected = null;
                
                    //全局单例instance
                    client.instance = this;
                
                    //初始化,从gate获取connector 然后链接
                    this.init = function () {
                
                        var pomelo = window.pomelo;
                        var route = 'gate.gateHandler.queryEntry';
                        var uid = "uid";
                        rid = "1";//频道
                
                
                        pomelo.init({
                            host: "127.0.0.1",
                            port: 3014,
                            log: true
                        }, function () {   // gate
                
                            pomelo.request(route, {
                                uid: uid
                            }, function (data) { // connector
                                //获取connector成功
                                pomelo.disconnect();
                                //链接connector
                                pomelo.init({
                                    host: data.host,
                                    port: data.port,
                                    log: true
                                }, function () {
                                    var route = "connector.entryHandler.enter";
                                    pomelo.request(route, {
                                        username: username,
                                        rid: rid
                                    }, function (data) {
                                    	//链接connector成功
                                        cc.log("[client.js]:" + JSON.stringify(data.users));
                                        cc.log("[client.js]:" + "connect success!");
                                        //初始化事件
                                        client.instance.lazyInit();
                
                                    });
                                });
                            });
                        });
                
                    }
                
                    //发送接口
                    this.send = function (msg) {
                        var route = "chat.chatHandler.send";
                        var target = "*";
                        pomelo.request(route, {
                            rid: rid,
                            content: msg,
                            from: username,
                            target: target
                        }, function (data) {
                
                        	cc.log("[client.js]:" + "  revc " +"   "  +  (JSON.stringify(data)));
                
                        });
                    }
                
                    //注册服务端事件
                    this.lazyInit = function () {
                        pomelo.on("onChat", this.onChat);
                        pomelo.on("onAdd", this.onAdd);
                        pomelo.on("onLeave", this.onLeave);
                        pomelo.on('disconnect', this.onDisconnected);
                
                    };
                
                };

在 app.js 中实例化客户端并注册事件回调:

        this.pomelo_client = new Client();
                        this.pomelo_client.init();
                
                
                
                        this.pomelo_client.onAdd = function (data) {
                            console.log("user online " + data.user);
                            console.log(JSON.stringify(data));
                            msgqueue.push("玩家:" + data.user + " 进入房间")
                            syncUI();
                
                        };
                
                
                
                        this.pomelo_client.onChat = function (data) {
                            //	console.log(  JSON.stringify( data));
                            console.log("recv:form " + data.from + " to " + data.target + "   say:" + data.msg);
                
                            if (data.target == '*') {
                
                                msgqueue.push("玩家:" + data.from + " 对所有玩家说: " + data.msg);
                            }
                            else {
                                msgqueue.push("玩家:" + data.from + " 对" + data.target + " 说: " + data.msg);
                            }
                
                            syncUI();
                
                        };
                
                
                
                        this.pomelo_client.onLeave = function (data) {
                            console.log("user offline " + data.user);
                            msgqueue.push("玩家:" + data.user + " 离开房间")
                            syncUI();
                
                        };
                
                
                        this.pomelo_client.onDisconnected = function (reason) {
                            cc.log("disconnect!!!!!");
                            msgqueue.push("失去服务器连接!");
                            syncUI();
                
                        };

限制界面上同时显示的消息条数,只保留最近 10 条:

    sync: function () {
                        layer.removeAllChildren(true);
                
                        var len = msgqueue.length;
                        var i = len - 10;
                        var k = 0;
                        for (i = i < 0 ? 0 : i  ; i < len; i++) {
                
                            k++;
                            var lab = new cc.LabelTTF(msgqueue[i], "Arial", 18);
                
                            lab.setHorizontalAlignment(3)
                            lab.x = cc.winSize.width / 2;
                            lab.y = 500 - 100 - 20 * k;
                            layer.addChild(lab);
                
                        }
                    }

测试结果

按 F11 运行时,如果提示 6050 端口被占用,可以打开 cmd 执行 netstat -ano 查看占用进程。通常是 web_server 的 node.exe 占用了该端口,杀掉该进程即可,不影响客户端测试。

cocos 客户端与浏览器客户端互通的测试结果如下:

关闭服务端后,客户端会提示失去连接: