引言
在使用ws过程中,传输内容都是明文可见的,我希望用户看不到我们发送的内容,至少增加阅读成本,同时提高一下传输效率,所以在传输过程中我在出入口处添加了加压和解压的方法。
zlib
服务器我用的是node.js实现,node.js有自带的zlib库,所以我直接就用自带的了。我们先来看下zlib这模块,zlib有很多压缩方法:
我们可以根据配置来选择需要的解压缩方法,首先我们先写两个方法,一个是压缩方法compress,一个是解压方法decompress。
const zlib = require('zlib');
const compress = function(str, type) {
switch (type) {
case 'gzip':
return zlib.gzipSync(str);
case 'deflate':
return zlib.deflateSync(str);
case 'deflateRaw':
return zlib.deflateRawSync(str);
default:
return str;
}
}
const decompress = function(str, type) {
switch (type) {
case 'gzip':
return zlib.gunzipSync(str).toString();
case 'deflate':
return zlib.inflateSync(str).toString();
case 'deflateRaw':
return zlib.inflateRawSync(str).toString();
default:
return str;
}
}
我们只需要在send方法中使用compress压缩下内容:
const send = function (msg, id) {
return new Promise((resolve, reject) => {
try {
const data = compress(JSON.stringify({id, msg}), 'deflateRaw');
... ...
} catch (err) {
reject(err);
}
});
}
在收到信息时候使用decompress解压下内容:
socket.on('message', (_data) => {
const data = decompress(_data, 'deflateRaw');
if (typeOf data !== 'string') return;
... ...
});
这样我们就完成了一个简单的服务器传输压缩功能。
pako
前端我选择用pako库来实现压缩资料的功能。一样实现两个方法compress和decompress。需要注意一下的是,Html5的websocket接收二进制数据格式有blob和arraybuffer,默认是blob,我们可以通过websocket.binaryType来指定收到的二进制数据的格式。
import pako from 'pako';
const compress = function (data, type) {
switch (type) {
case "gizp":
return pako.gzip(data);
case "deflate":
return pako.deflate(data);
case "deflateRaw":
return pako.deflateRaw(data);
default:
return data;
}
}
const decompress = async function (data, type) {
if (data instanceof Blob) {
data = await new Promise(resolve => {
const reader = new FileReader();
//byte为blob对象
reader.readAsArrayBuffer(data);
reader.onload = (e) => {
resolve(reader.result);
}
});
}
switch (type) {
case "gizp":
return pako.ungzip(data, { to: "string" });
case "deflate":
return pako.inflate(data, { to: "string" });
case "deflateRaw":
return pako.inflateRaw(data, { to: "string" });
default:
return data;
}
}
使用方法跟服务器的类似,就不详细说明了。最后我们在浏览器看下效果:
END