【发布时间】:2016-03-11 06:12:45
【问题描述】:
我有一个 node.js 脚本,它允许客户端连接并从外部脚本接收一些实时数据。
我刚刚将 node.js 和 socket.io 升级到当前版本(从
这是我当前的 node.js 脚本;
var options = {
allowUpgrades: true,
pingTimeout: 50000,
pingInterval: 25000,
cookie: 'k1'
};
var io = require('socket.io')(8002, options);
cp = require('child_process');
var tail = cp.spawn('test-scripts/k1.rb');
//On connection do the code below//
io.on('connection', function(socket) {
console.log('************ new client connected ****************', io.engine.clientsCount);
//Read from mongodb//
var connection_string = '127.0.0.1:27017/k1-test';
var mongojs = require('mongojs');
var db = mongojs(connection_string, ['k1']);
var k1 = db.collection('k1');
db.k1.find({}, {'_id': 0, "data.time":0}).forEach(function(err, doc) {
if (err) throw err;
if (doc) { socket.emit('k1', doc); }
});
//Run Ruby script & Listen to STDOUT//
tail.stdout.on('data', function(chunk) {
var closer = chunk.toString()
var sampArray = closer.split('\n');
for (var i = 0; i < sampArray.length; i++) {
try {
var newObj = JSON.parse(sampArray[i]);
// DO SOCKET //
socket.emit('k1', newObj);
} catch (err) {}
}
});
socket.on('disconnect', function(){
console.log('****************** user disconnected *******************', socket.id, io.engine.clientsCount);
socket.disconnect();
});
});
在旧版本的 socket.io 中,当客户端退出时,我得到以下登录调试;
info - transport end (undefined)
debug - set close timeout for client Owb_B6I0ZEIXf6vOF_b-
debug - cleared close timeout for client Owb_B6I0ZEIXf6vOF_b-
debug - cleared heartbeat interval for client Owb_B6I0ZEIXf6vOF_b-
debug - discarding transport
然后一切顺利,一切都很好。
当客户端退出时,使用新 (1.3.7) 版本的 socket.io,我得到以下登录调试信息;
socket.io:client client close with reason transport close +2s
socket.io:socket closing socket - reason transport close +1ms
socket.io:client ignoring remove for -0BK2XTmK98svWTNAAAA +1ms
****************** user disconnected ******************* -0BK2XTmK98svWTNAAAA
注意socket.io:client ignoring remove for -0BK2XTmK98svWTNAAAA这一行
但在那之后并且没有其他客户端连接到服务器,我仍然看到它试图将数据写入已经离开的客户端。 (在下面的示例中,这是我连接了 2 个客户端后得到的结果,这两个客户端都已断开连接。
socket.io:client ignoring packet write {"type":2,"data":["k1",{"item":"switch2","datapoint":{"type":"SWITCH","state":"0"}}],"nsp":"/"} +1ms
socket.io:client ignoring packet write {"type":2,"data":["k1",{"item":"switch2","datapoint":{"type":"SWITCH","state":"0"}}],"nsp":"/"} +3ms
我正在尝试阻止这种明显的新行为,以便一旦客户端断开连接并且服务器处于空闲状态,它就不会继续尝试发送数据。
我一直在玩 socket.disconnect 和 delete socket["id"],但我还是一样。
我尝试使用 io.close() 哪种方法有效 - 它启动了任何实际连接的客户端并让它们重新连接,但仍然让服务器坐在那里试图向已离开的客户端发送更新。
我是否遗漏了一些明显的东西,或者新版本的 socket.io 的处理方式发生了变化? migration doc 中没有关于此的内容。我发现的唯一其他结果是 2014 年 6 月的 this 错误报告,已标记为已关闭。从我的阅读来看 - 这似乎与我遇到的问题相同,但使用当前版本。
更新:我进行了更多测试,并将io.engine.clientsCount 添加到console.log 的两个实例中以跟踪它在做什么。当我连接 1 个客户端时,它会出现 1(如预期的那样),当我关闭该客户端时,它会变为 0(如预期的那样),这让我相信客户端连接已关闭并且 engine.io 知道这一点。那么为什么我仍然会看到所有“忽略数据包写入”行以及每个已断开连接的客户端的更多信息。
更新 2: 我已经更新了上面的代码以包含解析器部分和 DB 部分 - 这代表了完整的节点脚本,因为我认为我可能需要清理自己的客户。我已经尝试将以下代码添加到脚本中,希望它会但可惜不是:(
在连接事件中我添加了clients[socket.id] = socket;,在断开连接事件中我添加了delete clients[socket.id];,但它并没有改变任何东西(我可以看到)
更新 3: 感谢@robertklep,这是我真正在寻找的“事件处理程序泄漏”。发现后我也找到了this的帖子。
【问题讨论】:
-
看起来您自己的代码一直在写入已经关闭的套接字(您没有表明一旦客户端断开连接就清理数据库连接和 Ruby 进程)。
-
Ahhh - 这听起来很有趣 - 稍后我会用完整的代码更新问题,但我的旧节点/套接字 0.9 应用程序中从未有任何东西通过关闭的方式下。如果您有时间在格林威治标准时间 19:00 之后回来查看,我将更新代码中缺失的部分。可能需要一些关于如何进行清理的指示。
-
我的猜测是您之前的代码表现出相同的行为,但
socket.io只是没有记录任何内容 ;-) -
@robertklep - 如果您不介意将目光投向它,请使用完整的节点脚本更新上面的代码。这(显然)在“旧节点”中工作正常如果您想查看正在被引用的 ruby 文件,这可能会有点困难但并非不可能。
标签: node.js socket.io socket.io-1.0