所以我在node.js中有一个应用程序来读取CSGO演示,它解析文件,我希望每次更新实体时都会向客户端发送一个带有socket.io的事件。 它有效,但它只会触发" client.emit(' tick',' a');"但是console.log会正确地触发,任何人都可以帮我找出socket.io阻止发射的原因???
服务器代码
var server = require('http').createServer();
var io = require('socket.io')(server);
var fs = require('fs');
var jsgo = require('jsgo');
io.on('connection', function(client){
fs.readFile('train.dem', function (err, data) {
var demo = new jsgo.Demo();
demo.on('entity_updated', function (entity) {
console.log('entity_updated');
client.emit('tick', 'a');
});
demo.parse(data);
});
});
server.listen(3000);
客户代码
var socket = io('http://localhost:3000');
socket.on('connect', function() {
console.log('connected');
});
socket.on('tick', function (data) {
console.log('entity_updated');
});
socket.on('disconnect', function() {
console.log('disconnect');
});
答案 0 :(得分:1)
我可以使用您提供的文件(train.dem)重现此问题。 socket.io无法发送多条消息的原因是由于此声明:
demo.parse(data);
node.js是单线程环境,上面的语句阻止了事件循环。当我运行上述声明时,它将永远完成。我运行了超过15分钟的代码,但由于它正在进行的处理量,这个功能可能无法退出。由于事件驱动的单线程环境,节点无法发送消息。所有消息都被缓冲并等待此循环退出。
我在代码中添加了更多日志,您可以观察可写标记:
socket.io:server initializing namespace / +0ms
socket.io:server creating engine.io instance with opts {"path":"/socket.io"} +5ms
socket.io:server attaching client serving req handler +4ms
engine:socket sending packet "open" ({"sid":"SFD8FKG2G_MjW78SAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}) +0ms
engine:socket flushing buffer to transport +2ms
engine:socket executing batch send callback +6ms
socket.io:server incoming connection with id SFD8FKG2G_MjW78SAAAA +7s
engine:socket sending packet "message" (0) +5ms
new client
engine:socket might upgrade socket transport from "polling" to "websocket" +36ms
engine:socket flushing buffer to transport +2ms
engine:socket executing batch send callback +5ms
engine:ws received "2probe" +15ms
engine:ws writing "3probe" +2ms
readFile done null
started
server --> entity_updated for 1client.conn.transport.writable true
engine:socket sending packet "message" (2["tick","a"]) +258ms
engine:socket flushing buffer to transport +1ms
server --> entity_updated for 2client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +2ms
server --> entity_updated for 3client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +1ms
server --> entity_updated for 4client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 5client.conn.transport.writable false
使用for..loop可以重现相同的内容。检查以下代码:
for (i=0; i<10; i++)
{
console.log('server --> entity_updated for ' + count + 'client.conn.transport.writable ' + client.conn.transport.writable);
count++;
client.emit('tick', 'a');
}
以及下面的日志:
socket.io:server initializing namespace / +0ms
socket.io:server creating engine.io instance with opts {"path":"/socket.io"} +7ms
socket.io:server attaching client serving req handler +3ms
engine:socket sending packet "open" ({"sid":"b86YJD0sGGawVZseAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}) +0ms
engine:socket flushing buffer to transport +2ms
engine:socket executing batch send callback +6ms
socket.io:server incoming connection with id b86YJD0sGGawVZseAAAA +2s
engine:socket sending packet "message" (0) +6ms
new client
engine:socket might upgrade socket transport from "polling" to "websocket" +23ms
engine:socket flushing buffer to transport +4ms
engine:socket executing batch send callback +2ms
engine:ws received "2probe" +8ms
engine:ws writing "3probe" +5ms
readFile done null
started
ended
server --> entity_updated for 1client.conn.transport.writable true
server --> entity_updated for 1client.conn.transport.writable true
engine:socket sending packet "message" (2["tick","a"]) +100ms
engine:socket flushing buffer to transport +0ms
server --> entity_updated for 2client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +1ms
server --> entity_updated for 3client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 4client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 5client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 6client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +1ms
server --> entity_updated for 7client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 8client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 9client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
server --> entity_updated for 10client.conn.transport.writable false
engine:socket sending packet "message" (2["tick","a"]) +0ms
engine:ws received "5" +3ms
engine:socket got upgrade packet - upgrading +0ms
engine:socket flushing buffer to transport +1ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +1ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +0ms
engine:ws writing "42["tick","a"]" +1ms
engine:ws writing "42["tick","a"]" +1ms
engine:socket executing batch send callback +0ms
for循环结束后,socket / io层通过套接字写入数据。一旦demo.parse()完成处理,您的代码也会发生同样的情况。
您必须找出另一种从jsgo获取数据的方法,以便取消阻止事件循环并将其提供给socket.io。可能你可以在jsgo github上提出增强请求。
答案 1 :(得分:0)
每次更新enitity时,都必须在某些存储中保存套接字。
现在你可以尝试在变量中连接时保存套接字,但这对许多客户端都不起作用,因为每次连接新套接字时,变量都将使用新的套接字ID进行更新。
var server = require('http').createServer();
var io = require('socket.io')(server);
var fs = require('fs');
var jsgo = require('jsgo');
var socketId; // this will only store one id. store it in some data storage or create room for each user and emit in room
io.on('connection', function(client){
socketId = client.id;
fs.readFile('train.dem', function (err, data) {
var demo = new jsgo.Demo();
demo.on('entity_updated', function (entity) {
console.log('entity_updated');
if(io.sockets.connected[socketId]) //check if socket is still connected.
{
io.sockets.to(socket.socketId).emit('tick', 'a');
}
});
demo.parse(data);
});
});
server.listen(3000);