如何通过socket.io将数据流传输到客户端

时间:2018-02-05 16:35:28

标签: node.js sockets socket.io event-stream

我有socket.io从服务器向客户端发送基本对象。这个位工作正常。

现在想要使用§8.4.5.1/7 Closure types [expr.prim.lambda.closure]从服务器向客户端发送流(特别是块链查询的结果)。我在浏览器控制台中得到了意想不到的结果..

library(xgboost)

x = as.matrix(iris[, 1:4])
y = as.numeric(factor(iris[, 5]))-1

model <- xgboost(data = x, label = y, nrounds = 10)

new <- data.frame(Sepal.Length = 5.1,
                  Sepal.Width = 3.5,
                  Petal.Length = 1.4,
                  Petal.Width = 0.2)

#error because it is a data.frame
preds <- predict(model, newdata = new)

# Error in xgb.DMatrix(newdata, missing = missing) : 
#   xgb.DMatrix: does not support to construct from  list

# This works because data.frame is turned into a matrix
preds <- predict(model, newdata = as.matrix(new))

我在客户端控制台中看到的似乎是某种TCP套接字函数,

var io = require('socket.io')(server); var dsteem = require('dsteem') var es = require('event-stream') var util = require('util') var client = new dsteem.Client('https://api.steemit.com') var stream = client.blockchain.getBlockStream() /* This sends results to stdout, fine io.on('connection', function(socket){ stream.pipe(es.map(function(block, callback) { callback(null, util.inspect(block) + '\n') })).pipe(process.stdout); // And this sends a simple object to the client socket.emit('blockchainOps', {"Foo!":"Doo!"} ); }); */ // Putting both together sends strange connection data to client io.on('connection', function(socket){ socket.emit('blockchainOps', function() { stream.pipe(es.map(function(block, callback) { callback(null, util.inspect(block) + '\n'); })) }) });

任何人都可以帮助我了解发生了什么以及我做错了什么吗?

==编辑更新==

正如评论中所建议的,我已尝试event-stream来增强socket.io-stream

ƒ (){if(!n){n=!0;var r=a(arguments);u("sending ack %j",r),e.packet({type:i.ACK,id:t,data:r})}}

这次我得到一个在浏览器控制台中返回的套接字对象,它似乎不是我希望的流数据。

event-stream

2 个答案:

答案 0 :(得分:2)

如果有人在寻找有效的socket.io流示例

// server side
const { pipeline } = require('stream')
const server = require('http').Server().listen(8080)
const io = require('socket.io')(server)
const ss = require('socket.io-stream')

io.on('connection', (socket) => ss(socket).on('stream', (stream) => {
  pipeline(stream, process.stdout,  (err) => err && console.log(err))
}));


// client side
const client = require('socket.io-client')
const socket = client.connect('http://localhost:8080')

socket.on('connect', () => {
  const stream = ss.createStream()
  ss(socket).emit('stream', stream)
  pipeline(process.stdin, stream,  (err) => err && console.log(err))
});

答案 1 :(得分:1)

您使用socket.emit错误,您将ACK回调传递给客户端而不是您的信息流。请查看socket.emit signaturesocket.emit(eventName[, ...args][, ack])

你可能想要像

这样的东西
socket.emit('blockchainOps', client.blockchain.getBlockStream());

但是,我不认为普通的socket io支持像这样传递Stream。要将流管道传输到客户端,您可以使用socketio-stream。它看起来像这样:

var ss = require('socket.io-stream');
var stream = ss.createStream();

ss(socket).emit('blockchainOps', stream);
client.blockchain.getBlockStream().pipe(stream);

修改

在客户端上,您应该能够像这样读取您的信息流:

    <script src="socket.io/socket.io.js"></script>
    <script src="socket.io-stream.js"></script>
    ...
    ss(socket).on('blockchainOps', function(stream) {
       var binaryString = "";

       stream.on('data', function(data) {
           for(var i=0;i<data.length;i++) {
                binaryString+=String.fromCharCode(data[i]);
           }                
       });

        stream.on('end', function(data) {
             console.log(binaryString);
             binaryString = "";
       });
    });