nodejs websocket 收发二进制数据
ws模块可以很方便的完成websocket的收发功能,npm上的说明如下:
ws is a simple to use WebSocket implementation, up-to-date against RFC-6455, and probably the fastest WebSocket library for node.js.
server端代码:
'use strict';
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({ port: 5505 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data, flags) {
console.log('flags.binary: '+flags.binary+', flags.mask: '+flags.mask);
console.log('data:'+ typeof data);
console.log(data);
});
});
client端代码;
'use strict';
var WebSocket = require('ws');
var ws = new WebSocket('ws://127.0.0.1:5505/');
ws.on('open', function open() {
var array = new Uint8Array(4);
array[0] = parseInt(Math.random()*0xFF);
array[1] = parseInt(Math.random()*0xFF);
array[2] = parseInt(Math.random()*0xFF);
array[3] = parseInt(Math.random()*0xFF);
console.log(array);
ws.send(array, {binary: true, mask: true});
});
其中一次的输出分别如下:
// client端
Uint8Array { '0': 47, '1': 2, '2': 236, '3': 92 }
// server端
flags.binary: true, flags.mask: undefined
data:object
<Buffer 2f 02 ec 5c>
注意:如果client端直接发送字符串,则server端则会自动判断是string还是object:
// client端的代码
ws.send('1234');
// server端的输出
data:string
1234
nodejs 文件 读写二进制数据
fs模块是nodejs的内建模块,使用该模块可以方便的进行各种文件操作。官方说明如下:
File I/O is provided by simple wrappers around standard POSIX functions. To use this module do require(‘fs’). All the methods have asynchronous and synchronous forms.
其中读写二进制文件的代码如下:
'use strict';
var fs = require('fs');
var array = new Uint8Array(4);
array[0] = parseInt(Math.random()*0xFF);
array[1] = parseInt(Math.random()*0xFF);
array[2] = parseInt(Math.random()*0xFF);
array[3] = parseInt(Math.random()*0xFF);
console.log(array);
var buf = new Buffer(array);
console.log(buf);
fs.writeFile('test.bin', buf, function (err) {
console.log('writeFile OK');
});
fs.readFile('test.bin', function (err, data) {
console.log('readFile OK');
console.log(data);
});
某次的输出结果如下:
$ node fileWithBinary.js
Uint8Array { '0': 125, '1': 98, '2': 225, '3': 250 }
<Buffer 7d 62 e1 fa>
writeFile OK
readFile OK
<Buffer 7d 62 e1 fa>
$ hexdump test.bin -C
00000000 7d 62 e1 fa |}b..|
00000004
从输出结果来看,能够正确的写入二进制数据到文件中,再读取出来也是相同的数据。
nodejs redis 读写二进制数据
通过nodejs-redis模块我们可以很方便的操作redis,npm上的说明如下:
This is a complete Redis client for node.js. It supports all Redis commands and focuses on performance.
redis是支持二进制数据的,通过nodejs写入二进制数据的代码如下:
'use strict';
var redis = require("redis")
var client = redis.createClient();
var array = new Uint8Array(4);
array[0] = parseInt(Math.random()*0xFF);
array[1] = parseInt(Math.random()*0xFF);
array[2] = parseInt(Math.random()*0xFF);
array[3] = parseInt(Math.random()*0xFF);
console.log(array);
var buf = new Buffer(array);
console.log(buf);
client.set('test', buf, function(err, response) {
console.log('set OK, response:' + response);
});
上面代码的输出以及通过redis-cli读取的结果分别如下:
$ node redisWithBinary.js
Uint8Array { '0': 74, '1': 245, '2': 237, '3': 116 }
<Buffer 4a f5 ed 74>
set OK, response:OK
$ redis-cli get test
"J\xf5\xedt"
注意: redis-cli对于可打印内容和不可打印的字符分别使用字符和十六进制转义进行显示。
使用nodejs读取redis中的二进制数据,代码如下:
client.get('test', function(err, res) {
console.log('res typeof:'+ typeof res);
console.log('res:' + res);
var buf = new Buffer(res);
console.log(buf);
});
输出结果:
res typeof:string
res:J��t
<Buffer 4a ef bf bd ef bf bd 74>
问题出现了:
1. 通过get读取出来的数据类型是string,并不是raw data
2. 将该string转为Buffer后,对于不认识的字符直接转换为ef bf bd,通过测试,在设置了encoding格式为ascii和binary后,输出都是,同样是转为了固定的一个值fd
对于res字符串中的内容,我们可以通过下述代码进行仔细确认:
client.get('test', function(err, res) {
console.log('res typeof:'+ typeof res);
console.log('res:' + res);
for (var i =0; i < res.length; i++) {
console.log('res.charCodeAt(i): 0x'+res.charCodeAt(i).toString(16));
}
});
输出结果:
res typeof:string
res:J��t
res.charCodeAt(i): 0x4a
res.charCodeAt(i): 0xfffd
res.charCodeAt(i): 0xfffd
res.charCodeAt(i): 0x74
到这里,我们就确认了,redis本身是支持二进制的读写的,但是nodejs-redis在进行回调的时候已经对二进制数据进行了解码,当遇到无法识别的字符直接转换成了0xFFFD对应的字符,WTF。
总结
nodejs/redis在二进制的支持上还是有很多问题,目前不建议使用二进制进行存取。