我正在构建一个平台,多个用户可以互相交互,并在另一个用户以某种方式与自己交互时得到通知。例如,发送消息,发送请求或更新服务器上的某些协作对象。这里没什么特别的。 因此,我喜欢在带有express(前端位于angular 7中)的节点服务器上使用Socket.io,以尽可能保持实时性。
我想知道我是否真的需要引入名称空间和房间,因为我当前的实现应该可以正常工作。您能否告诉我,我的实现类型是否有问题?
我正在使用某种套接字连接存储区作为Map,所有活着的套接字连接都在其中。这是我的服务器端实现的示例:
// <userId, socket>
var Connections = new Map();
removeConnection = function(socket) {
console.log("removing User with Id = " + socket.userId);
Connections.delete(socket.userId);
}
io.on('connection', (socket) => {
socket.on('register', (userId) => {
// do some authentication here..
socket.userId = userId;
Connections.set(userId, socket);
console.log("User registered with id " + userId);
});
socket.on('disconnect', () => {
removeConnection(socket);
});
socket.on('new_message', (data) => {
// persist data in DB and so on..
socket.emit('new_message', data);
var receiver = Connections.get(data.receiverId);
// if receiver is online send message
if(receiver) {
receiver.emit('new_message', data);
}
});
});
答案 0 :(得分:2)
如果您不使用任何收件人选择(例如,单个收件人或命名空间/房间),则每封邮件都会传递给每个客户端。假设每个客户端在连接后都会发送“ hello”消息。 “ hello”消息的数量将随着您的客户数量呈指数增长。
取决于您计划扩展应用程序的大小,这可能会导致大量流量:n条消息将导致n²个事务... 1000个用户发送1条消息,每个用户已经有1.000.000个事务。
为使沟通更加有效,您可以执行以下任何步骤:
直接消息应仅发送给该用户,而不是整个平台上的广播。您可以使用connection.emit(“ the message”)命令执行此操作。 io.emit(“ the message”)将发送给每个连接的客户端
消息可以使用“房间”来实现。任何用户都可以预订一些房间,以接收这些通知。所有其他消息都不会被垃圾邮件淹没。 (https://socket.io/docs/rooms-and-namespaces/)
另一个问题可能是隐私...如果用户A向用户B发送消息,则您不希望用户C,D,E ..也接收该广播。即使您的客户端过滤掉了不适合用户的邮件,该信息仍将以纯文本形式发送给所有用户,我认为这是不必要的隐私侵害。
关于收件人选择以及发送消息的不同方法,这是一个很好的备忘单: https://socket.io/docs/emit-cheatsheet/
您的代码接收到来自任何已连接客户端的消息,并将其仅转发给相应的收件人(如果在地图中找到)。这对于用户之间的直接消息传递是很好的。如果您要广播某些协作项目的更新信息,则应使用如上所述的房间和名称空间。