cocoscreator与nodejs网络基础通信(二)

上一章节中简单讲诉了前端使用websocket部分,这一章节讲诉后端使用websocket部分。

后端使用的nodejs,websocket包使用的websocket地址,可点击查看详细文档。

websocket基于事件的编程模型与nodejs中自定义事件相差无几,nodejs的事件驱动的方式十分擅长与大量的客户端保持高并发连接,所以websoket与nodejs的配合感觉很完美。

相比http,我觉得websocket更接近于传输层协议,它并没有在http的基础上模拟服务器端的推送,而是在TCP上定义独立的协议。让人迷惑的部分在于websocket的握手部分是由http完成的,让人觉得它可能是基于http实现的。

这里就不展开讲了,主要还是讲解怎么使用。

至于为什么用这个websocket包,因为这个websocket包简单好用。

下面直接进入正题:

创建server的核心代码段

function websocket_connection(s, handler) {
    this._internal_s = s;
    this.h = handler;
	s.socket.setTimeout(40000); //设置超时时间
    var self = this;
	//监听超时事件
    s.socket.addListener("timeout", function() {
        _log("client is closed by timeout.");
        self.destroy();
    });
	//console.log(s);
    s.on("error", function () {
        self._internal_s = null;
    });
    s.on("close", function () {
        var close_fn = self.h[SYS_MSG.CLOSE];
        if (close_fn != undefined && typeof close_fn === "function") {
            _log("recv msg id ---> " + "_close");
            close_fn({}, self);
        }
    });
}

exports.start_websocketserver = function (port, handler, protoroot) {

    var ws = require("nodejs-websocket");
    var server = ws.createServer(function (s) {
		//当有客户端来连接时,会触发这个回调函数。
        var self = new websocket_connection(s, handler);
        //_log(port); 
        self.remoteAddress = self._internal_s.socket.remoteAddress;
        self.remotePort = self._internal_s.socket.remotePort;
        self.localAddress = self._internal_s.socket.localAddress;
        self.localPort = self._internal_s.socket.localPort;
        //_log(self);
		//监听二进制数据事件
        s.on("binary", function (inStream) {
            //创建buffer对象,收集二进制数据
            var buf = new Buffer.alloc(0);
            //读取二进制数据的内容并且添加到buffer中
            inStream.on('readable', function () {
                var newBuf = inStream.read()
                if (newBuf)
                    buf = Buffer.concat([buf, newBuf], buf.length + newBuf.length)
            })
            inStream.on('end', function () {
                //读取完成二进制数据后,处理二进制数据
                var msgid = "" + buf.readInt16BE(0);
                _log("recv msg id ---> " + msgid);
                var body_buffer = new Buffer.alloc(buf.length - 2);
                buf.copy(body_buffer, 0, 2, buf.length - 2);
				//body_buffer即为我们需要的二进制数据
                buf = null;
            })
        });

        s.on("text", function (data) {
            try {
                var msg = JSON.parse(data);
            }
            catch (e) {

            }
        });

        var connect_cb = self.h[SYS_MSG.CONNECT];
        console.log("connect_cb");
        if (connect_cb != undefined && typeof connect_cb === "function") {
            _log("recv msg id ---> " + "_connect");
            connect_cb({}, self);
        }

    }).listen(port);

    _log("websocket listen on port : " + port + " ok!");

    return server;
};

ws.createServer(cb(s))返回一个server对象,server对象调用listen设置要监听的端口。handler是消息号与处理函数的对应关系。

当有客户端向服务器发起连接并且连接成功时,会触发一次cb,s则表示与该客户端建立的这条新连接。

text类型数据和binary类型接收时触发的是不同的事件,text数据接收只会触发一次函数回调。但是binary数据接收,可能会触发多次,每次接收到的数据可能都只有一部分,所以需要将触发readable事件读取的数据拼接起来,当所有数据接收完成的时候,会触发end事件。

需要注意的是,以前在使用nodejs-websocket的setTimeout时有一个小问题,当一个客户端和服务器只建立成功了TCP连接但是并没有升级协议为websocket,此时并不会触发cb,我们拿不到s变量所以不能设置超时,也无法断开连接,不确定最新版本是否还有这个问题。可以修改nodejs-websocket的Connection.js文件,设置超时。

服务器端还需要处理很多异常的情况,上述只是一个简单的应用。

下一章将会讲解整合protobuf。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值