我面临着一个奇怪的问题,我自己无法解决。我已经建立了一个设置,通过 Django/Celery 定期任务发送 JSON 序列化消息。此任务通过 Redis 与节点.js服务器进行通信。Node.js 通过 socket.io 处理与 Web 浏览器的通信。
姜戈/芹菜任务
@periodic_task(run_every=crontab()) # every minute
def process_channels():
r = redis.StrictRedis(host='localhost', port=6379, db=0)
for i in xrange(1,21): # 1..20
data_dict = {}
data_dict['time'] = time.ctime(time.time())
data_dict['message'] = os.urandom(10).encode('hex')
r.publish('channel', json.dumps(data_dict) )
time.sleep(2)
节点.js服务器
var http = require('http');
var server = http.createServer().listen(4000);
var io = require('socket.io').listen(server);
var querystring = require('querystring')
var redis = require('socket.io/node_modules/redis');
var sub = redis.createClient();
sub.subscribe('channel');
io.sockets.on('connection', function (socket) {
// grab message from Redis and send to client
sub.on('message', function(channel, message) {
console.log(message + ' ' + channel + ' ' + socket.id);
socket.send(message);
});
socket.on('disconnect', function() {
console.log('disconnected')
});
});
索引.html
$(document).ready(
function() {
var socket = io.connect('localhost', {
port: 4000
});
socket.on('connect', function() {
console.log("connecting");
});
socket.on('message', function(message) {
// deserialize message from DJANGO
var data = JSON.parse(message);
//Append message to the bottom of the list
$('#comments').append('Time: ' + data.time + '<br />');
$('#comments').append('Message: ' + data.message + '<br /><br />');
} });
});
很简单。该任务通过 Redis 将随机生成的消息发送到节点服务器,并在节点服务器中将其发送到浏览器。如您所见,我正在将消息和 socket.id 记录在节点服务器中。
一切都按预期工作,直到我重新加载页面。当我第一次加载页面时,服务器控制台会打印类似的东西:
{"message": "85105676e21512a33e72", "time": "Fri Oct 18 22:33:10 2013"} channel 94k39P2j9dMv1JEZRW6Q
当我重新加载页面时,会出现这种情况:
disconnected
{"message": "c3e93646d60a5a6727f6", "time": "Fri Oct 18 22:33:18 2013"} channel 94k39P2j9dMv1JEZRW6Q
{"message": "c3e93646d60a5a6727f6", "time": "Fri Oct 18 22:33:18 2013"} channel wJwsRvpgEks7g1AURW6R
同一消息已发送两次。每次我重新加载页面时,消息都会再次发送一次。查看socket.ids(第3个字段),似乎是套接字在重新加载之前未正确断开连接,并且服务器仍在通过该套接字发送消息。我不明白这种行为。调用了"断开连接"方法,因此应以任何方式处理它。有人可以帮助我吗?
提前非常感谢。
在客户端尝试 socket.once() 而不是 socket.on()。
socket.once('message', function() {
...
}
问题可能是每次重新加载页面时,都会附加多个侦听器。我遇到了类似的问题,".once()"是我能找到的唯一解决方案。
如果这没有帮助,您可以尝试探索此处发布的类似问题。希望对:)有所帮助https://github.com/LearnBoost/socket.io/issues/997