参考:

HTML5+NodeJs实现WebSocket即时通讯 (某人的blog)

nodejs-websocket使用示例  (www.npmjs.com网站,有示例)

Buffer API (nodejs api 中文版)

 

nodejs-websocket + protobufjs

 

 

 一 安装nodejs-websocket

在服务端项目文件夹下,新建一个pageage.json

{
  "name": "realtime-server",
  "version": "0.0.1",
  "description": "my first realtime server",
  "dependencies": {
    "nodejs-websocket": "^1.7.2",
    "protobufjs": "^6.8.8"
  }
}

 

在服务端项目文件夹下shift+右键,在此处打开命令窗口,输入

npm install nodejs-websocket

 

安装完毕后,项目目录下会增加node_modules文件夹

 

  

二 安装protobufjs

在服务端项目文件夹下shift+右键,在此处打开命令窗口,输入

npm install protobufjs

 

输入后回车,等待安装完毕,如下图:

 

三 准备测试用.proto文件

准备一个测试用的proto文件,如下

login.proto

//登录
package login;

//登录请求
message LoginReq{
	required int32 uid = 1;      //用户id
}

 

proto文件转成.js

将login.proto放在服务端项目文件夹下

shift+右键,打开命令窗口,生成js

pbjs -t static-module -w commonjs -o login.js login.proto

生成d.ts (服务端不需要,客户端需要)

pbts -o login.d.ts login.js

 四 服务端代码

 服务端连接成功后,等待接收。 如果接收到登录请求,则解析loginReq,然后返回一个loginReq。

直接使用login.proto文件示例:

var ws = require("nodejs-websocket");
var protobufjs = require("protobufjs");
var root = protobufjs.loadSync("./login.proto");   //直接使用login.proto文件

console.log("开始创建websocket");
var server = ws.createServer(function(conn){
	console.log("连接成功");
    conn.on("binary", function (inStream) {
		console.log("接收消息");
		var data;
		inStream.on("readable", function () {
            data = inStream.read();
        })
		inStream.on("end", function () {
            console.log("Received " + data.length + " bytes of binary data");
			
			//解析接收的数据,cmd
			var cmd = data.readUInt16BE(0);
			console.log("接收数据的cmd:",cmd);
			let bytes = Buffer.from(data,1);
			//解析接收的数据,loginReq
			var LoginReq = root.lookupType("login.LoginReq");
			var loginReq = LoginReq.decode(bytes);
			console.log("接收数据的uid:", loginReq.uid);
			
			
			
			//发送的数据,loginReq
			var sendLoginReq = LoginReq.create();
			sendLoginReq.uid = 123;
			var sendData = LoginReq.encode(sendLoginReq).finish();
			//发送的数据,cmd
			var sendBuffer = Buffer.alloc(2);
			sendBuffer.writeInt16BE(100);
			//拼接数据并发送
			var totalBuffer = Buffer.concat([sendBuffer,sendData],sendData.length + sendBuffer.length);
			conn.sendBinary(totalBuffer);
        })
		
        
    })
    conn.on("close", function (code, reason) {
        console.log("关闭连接")
    });
    conn.on("error", function (code, reason) {
        console.log("异常关闭")
    });
}).listen(8001)
console.log("开始创建websocket完毕");

 

使用转换后login.js文件示例:

var root = require("./login");    //使用login.js文件
 
//连接成功
io.on('connection', function(socket){
    console.log('a user connected');
    //监听登录请求
    socket.on('login', function(data,callback){         
         //解析登录数据
        var loginReqObj = root.login.LoginReq.decode(data);
        console.log("请求登录的用户:",loginReqObj.uid);
        //返回登录响应
        let loginResObj = root.login.LoginRes.create();
        loginResObj.code = 200;
        var buffer = root.login.LoginReq.encode(loginResObj).finish();
        socket.emit('login', buffer);
    });
});

  

 

五 客户端代码

客户端请求连接服务端,连接成功后发送登录请求loginReq

	/**连接成功*/
	private onConnect(e:egret.Event){
		console.log("ClientSocket 连接成功");
		this.resetReconnect();
		App.EventMananger.sendEvent(ClientSocket.SOCKET_CONNECT);

		//测试
		let loginData:login.LoginReq = new login.LoginReq();
		loginData.uid = 123;
		let buffer = login.LoginReq.encode(loginData).finish();
		this.send(100, buffer);
	}
	
	/**
	 * 发送数据
	 * @param cmd 数据协议
	 * @param sendByte 发送的数据
	 */ 
	public send(cmd:number, sendByte:Uint8Array){
		console.log("ClientSocket 发送:",cmd);
		//发送的数据cmd+proto
		let sendByteArray = new egret.ByteArray(sendByte);
		let byteArray:egret.ByteArray = new egret.ByteArray();
		byteArray.writeUnsignedShort(cmd);
		byteArray.writeBytes(sendByteArray);
		//发送
        this.socket.writeBytes(byteArray);
		this.socket.flush();
	}

	/**接收数据*/
	private onReceive(e:egret.Event){
		//读取socket数据
		var byte:egret.ByteArray = new egret.ByteArray();
        this.socket.readBytes(byte);
		//读取cmd+proto
		let cmd:number = byte.readUnsignedShort();
		console.log("接收数据,cmd:",cmd);
		//读取loginReq
		let revByteArray:egret.ByteArray = new egret.ByteArray();
		byte.readBytes(revByteArray);
		let buffer:login.LoginReq = login.LoginReq.decode(revByteArray.bytes);
		console.log("接收数据,uid:",buffer.uid);
	}

  

六 测试结果  

 运行服务端和客户端

1. 客户端请求连接服务端

2. 连接成功后,客户端发送登录请求loginReq

3. 服务端接收到登录请求,解析loginReq并打印。 然后再返回一个loginReq。

4. 客户端接收到服务端返回的loginReq,解析并打印。

 

服务端输出:

 

客户端输出:

 

 到此,一个简单的nodejs-websocket + protobufjs服务单搭建和联调测试完成。

 

问题:

一 nodejs服务端关于Buffer的操作

看了一下Buffer的Api,没有找到writeBytes的方法,只有concat来拼接数据。

posted on 2019-03-18 10:39  gamedaybyday  阅读(1034)  评论(1编辑  收藏