我正在编写自己的基于事件的 websocket 包装器,基于节点的 ws 包,并且在服务器端分离客户端时遇到了麻烦。
我设置了一个测试场景,我的客户端向服务器发送一条消息,服务器向同一个客户端发送一个“ping”。
发生的情况是我的测试场景与第一个连接的客户端完美配合,但是一旦另一个客户端连接,来自第一个客户端的消息将 ping 到另一个客户端(来自第二个客户端的消息将正确地 ping 到第二个客户端)。
感觉 WebSocket 以某种方式在两个客户端之间共享,但我似乎无法找到发生这种情况的位置。
//SERVER CODE
let events = {};
function WebSockServer(port) {
//Init server
const wss = new WebSocket.Server({
port,
clientTracking: true
}, () => {
if (events['open']) {
events['open'].callback();
}
});
wss.on('connection', ws => {
ws.id = uuidv4();
let sock = new WebSock(ws, wss);
if (events['connection']) {
events['connection'].callback(sock);
}
ws.on('message', json => {
console.log('received message from ' + ws.id);
const message = JSON.parse(json);
//Check flags
for (let key in message.flags) {
if (key === 'binary' && message.flags[key].length > 0) {
message.flags[key].forEach(binary => {
const parsed = Buffer.from(message.data[binary], 'utf-16');
message.data[binary] = parsed;
});
}
}
//Check if event handler exists & check if event is only to be triggered once
if (events[message.event] && !events[message.event].once) {
events[message.event].callback(message.data);
}
else if (events[message.event] && events[message.event].once) {
events[message.event].callback(message.data);
delete events[message.event];
}
else {
return;
}
});
ws.on('close', () => {
if (events['close']) {
console.log('client disconnected');
events['close'].callback(ws.id);
}
wss.clients.delete(ws);
});
});
//Create an event handler
this.on = function on(event, callback) {
events[event] = {callback, once: false};
return this;
}
wss.on('error', err => {
console.log('Server shut down.');
});
}
function WebSock(ws, wss) {
this.ws = ws;
this.id = ws.id;
//Create an event handler
this.on = function on(event, callback) {
events[event] = {callback, once: false};
return this;
}
//Create an event handler for one time use
this.once = function once(event, callback) {
events[event] = {callback, once: true};
return this;
}
//Emit message to socket
this.emit = function emit(event, data) {
let flags = {
binary: []
};
//Check for binary data
for (let key in data) {
if (Buffer.isBuffer(data[key])) {
const stringified = data[key].toJSON();
data[key] = stringified;
flags.binary.push(key);
}
}
const payload = JSON.stringify({event, data, flags});
this.ws.send(payload);
return this;
}
//Emit message to specific socket
this.emitTo = function emitTo(id, event, data) {
let destination;
let flags = {
binary: []
};
//Find socket
for (let socket of wss.clients) {
if (socket.id === id) {
destination = socket;
break;
}
}
//Check for binary data
for (let key in data) {
if (Buffer.isBuffer(data[key])) {
const stringified = data[key].toJSON();
data[key] = stringified;
flags.binary.push(key);
}
}
//Send message to socket
if (destination) {
//Check type
if (typeof event != 'string' || typeof data != 'object') {
throw new TypeError('event must be a string, data must be an object');
}
const payload = JSON.stringify({event, data, flags});
destination.send(payload);
return this;
}
}
}
module.exports = WebSockServer;
//CLIENT CODE
function webSock(url) {
const ws = new WebSocket(url);
let events = {};
//Create an event handler
this.on = function on(event, callback) {
events[event] = {callback, once: false};
return this;
}
//Create an event handler for one time use
this.once = function once(event, callback) {
events[event] = {callback, once: true};
return this;
}
//Emit message to server
this.emit = function emit(event, data) {
let flags = {
binary: []
};
//Check for binary data
for (let key in data) {
if (Buffer.isBuffer(data[key])) {
const stringified = data[key].toJSON();
data[key] = stringified;
flags.binary.push(key);
}
}
const payload = JSON.stringify({event, data, flags});
ws.send(payload);
return this;
}
ws.on('open', () => {
if (events['open']) {
events['open'].callback(ws);
}
});
ws.on('close', () => {
if (events['close']) {
events['close'].callback();
}
})
ws.on('message', json => {
const message = JSON.parse(json);
//Check flags
for (let key in message.flags) {
if (key === 'binary' && message.flags[key].length > 0) {
message.flags[key].forEach(buffer => {
const parsed = Buffer.from(message.data[buffer]);
message.data[buffer] = parsed;
});
}
}
//Check if event handler exists & check if event is only to be triggered once
if (events[message.event] && !events[message.event].once) {
events[message.event].callback(message.data);
}
else if (events[message.event] && events[message.event].once) {
events[message.event].callback(message.data);
delete events[message.event];
}
else {
return;
}
});
}
module.exports = webSock;
任何帮助将不胜感激,我确定我遗漏了一些明显的东西。