使用 socket.io 和空消息队列向特定客户端发送消息
Posted
技术标签:
【中文标题】使用 socket.io 和空消息队列向特定客户端发送消息【英文标题】:Sending message to specific client with socket.io and empty message queue 【发布时间】:2011-10-18 07:59:53 【问题描述】:socket.io 我快疯了! 文档太糟糕了,根本不是真的。
我想通过 socket.io 向特定客户端发送反馈
我的服务器端是这样的:
app.get('/upload', requiresLogin, function(request, response)
response.render('upload/index.jade');
io.sockets.on('connection', function (socket)
console.log('SOCKET ID ' + socket.id);
io.sockets.socket(socket.id).emit('new', 'hello');
);
);
客户端看起来像这样:
$(document).ready(function()
var socket = io.connect('http://localhost:80/socket.io/socket.io.js');
socket.on('new', function (data)
console.log(socket.id);
console.log(data);
//$('#state').html(data.status);
);
);
但是客户端什么也不做。我几乎尝试了一切。有人可以告诉我我做错了什么,拜托! :(
【问题讨论】:
【参考方案1】:向特定客户端发送消息,将连接到服务器的每个消息保存在一个对象中。
var socketio = require('socket.io');
var clients = ;
var io = socketio.listen(app);
io.sockets.on('connection', function (socket)
clients[socket.id] = socket;
);
然后您可以稍后执行以下操作:
var socket = clients[sId];
socket.emit('show', );
【讨论】:
那行不通。我做了一个简单的测试:var soc; io.sockets.on('connection', function (socket) soc = socket; );从每条路线外面。而在我的上传功能中,我使用了 soc.emit('news', 'bla') 没有任何反应...... 正如我之前所说:上传文件时不能发送事件。但是这种方法是有效的,当你有相应的 id 时,你可以向特定的客户端发送消息。 :-/ 对不起,我误解了你。所以没有办法从路由函数触发到特定客户端的消息? 是的,有。您必须将所有连接到您的服务器的客户端保存在客户端对象中(参见示例),并且当您拥有套接字 ID 时,您可以直接通过该对象访问套接字。但上传时不能这样做... 你到底想做什么?删除旧连接?只需在客户端断开连接时执行delete clients[socketId];
,它将从clients
哈希中删除。【参考方案2】:
通过 socket.io 向特定客户端发送反馈的几种方法包括:
正如 pkyeck 所说,将所有客户端保存到一个对象中,以便稍后在路由处理程序中发送给这些特定客户端,例如:
var sessionsConnections = ;
sio.on('connection', function (socket)
// do all the session stuff
sessionsConnections[socket.handshake.sessionID] = socket;
);
或者,使用 socket.io 对房间的内置支持 - 为每个客户端订阅一个连接的房间并通过路由处理程序中的这个房间发送,例如:
sio.on('connection', function (socket)
// do all the session stuff
socket.join(socket.handshake.sessionID);
// socket.io will leave the room upon disconnect
);
app.get('/', function (req, res)
sio.sockets.in(req.sessionID).send('Man, good to see you back!');
);
致谢:
http://www.danielbaulig.de/socket-ioexpress/#comment-1158
请注意,这两个示例解决方案都假定 socket.io 和 express 已配置为使用相同的会话存储,因此引用相同的会话对象。有关实现此目的的更多详细信息,请参阅上面和下面的链接:
https://github.com/LearnBoost/socket.io/wiki/Authorizing
【讨论】:
只想说使用会话 ID 作为房间是一个很好的建议。帮我解决了我遇到的问题,谢谢:) 似乎 socket.io 1.0 已经内置了对每个套接字方法的房间的支持:socket.io/docs/rooms-and-namespaces 房间应该注意集群。像其他答案一样将套接字保存在本地内存中可能会导致内存泄漏并且无法扩展。【参考方案3】:两件事
1) 您确实应该将您的 io.sockets.on(..)
放在您的 app/update
路由之外,以防止为客户端添加多个侦听器。
2) io.sockets.socket(id);不应该用,应该是socket.emit('new', 'hello')
【讨论】:
好吧,这也是个问题 io.connect('localhost:80/socket.io/socket.io.js');但是当我想在上传过程中发送消息时怎么办?然后我需要存储客户端 ID 并使用 io.sockets.socket(socket.id).emit('new', 'hello');还是不行? 据我所知,通过表单上传文件时套接字连接没有断开。 好的,最后一个问题。是否有可能清空消息队列?当我重新进入视图时,我收到了所有旧的按摩...... @vboy 你说的是哪个消息队列? socket.io 内部为客户端未收到的消息维护的消息队列?【参考方案4】:在 socket.io 1.0 中,这就是它的工作方式。它可能适用于较低版本,但我不能保证。
socket.to(socket_id_here).emit('new', 'hello');
之所以有效,是因为 socket.io 会自动将套接字添加到具有连接时套接字 ID 的房间。
另外,如果您打算升级到 1.0 版,那么 api 会有很多更改,因此您有时必须更改一些代码才能使其在 1.0 中工作。
【讨论】:
【参考方案5】:在 Socket.io 1.0+ 中执行此操作的正确方法是:
io.to(users_socket_id).emit('new', 'hello');
您还可以将房间名称替换为“users_socket_id”以发送到特定的 socket.io 房间。
【讨论】:
【参考方案6】:首先,你不能在客户端使用socket.id
。
然后换行
var socket = io.connect('http://localhost:80/socket.io/socket.io.js');
到
var socket = io.connect('http://localhost:80/');
【讨论】:
【参考方案7】:我认为 io.sockets.socket 已被删除,并且一直是 Socket.IO 中的问题 (https://github.com/socketio/socket.io/issues/1618)。
您可以使用 io.sockets.connected[socket.id] 并存储 socket.id 以通过用户名与用户进行引用:
var usernames = ;
usernames[username] = socket.id;
// Sending the message
io.sockets.connected[usernames[username]].emit(...);
我在文档的任何地方都没有看到它,所以我可以看到这个问题没有得到回答。此外,如果您没有通过用户名获得任何参考,您可以尝试:
users[socket.id] = socket.id;
复制键和值以便于访问。
如下所述,使用 io.clients 可能还有另一种方法,但我没有使用过那种方法。
其他解决方案:Send message to specific client with socket.io and node.js
【讨论】:
【参考方案8】:你试过用吗?
var socket = io.connect('http://localhost:80/');
【讨论】:
【参考方案9】:我厌倦了最新版本的 node 和 socket.io 下面我将发布完整的代码
<ul id="messages"></ul>
<form action="">
<input id="id1" /><button>Send</button>
</form>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var io = io.connect();
$('form').submit(function()
io.emit('drumevent', $('#id1').val());
$('#id1').val('');
return false;
);
io.on('drumevent', function(msg)
console.log(msg);
$('#messages').append($('<li></li>').text(msg.message+' quantity = '+msg.quantity));
);
</script>
服务器端代码
var usernames = ;io.on('connection', function(socket)usernames["username"] = socket.id;
socket.on('drumevent', function(msg)
var socketId = socket.id;io.to(socketId).emit('drumevent', data);
【讨论】:
以上是关于使用 socket.io 和空消息队列向特定客户端发送消息的主要内容,如果未能解决你的问题,请参考以下文章
使用 socket.io 向特定客户端发送消息,同时套接字 id 快速变化
如何将 socket.io 与 graphql 订阅一起使用?
node.js socket.io 如何发射到特定的客户端?