Socket.io不会发射超过1个事件

所以我在node.js中有一个应用程序来读取CSGO演示程序,它parsing了这个文件,并且我希望每次更新一个实体时,都会向客户端发送一个带有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'); }); 

我能够通过使用您提供的文件(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循环结束,套接字/ IO层将数据写入套接字。 一旦demo.parse()完成处理,您的代码也会发生同样的情况。

你将不得不找出一种从jsgo获取数据的替代方法,以便解除对事件循环的阻塞并将其提供给socket.io。 可能你可以在jsgo github上提出增强请求。

每次更新实体时,都必须将套接字保存在某个存储中。

现在你可以尝试在variables中连接时保存套接字,但是这对许多客户端不起作用,因为每次连接新的套接字时,variables都将被更新为新的套接字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);