WebSocket在15-20分钟的数据流后停止接收数据-NodeJS

时间:2019-05-09 14:46:22

标签: node.js sockets

代码

var websock = net.createServer(function(sock) {
  sock.pipe(sock);
  sock.setEncoding('utf8');
  sock.setKeepAlive(true);

  sock.on("data", function(d) {
       console.log("websock", d);
  });

  sock.on('end', function() {
      console.log('websock disconnected');
  });
});

websock.listen(777, '127.0.0.1');

几分钟〜15分钟后,sock.on(“ data”,function(){})中的回调代码似乎无法正常工作。为什么会这样呢?我检查了console.log,没有带有字符串“ websock connected”的日志。

如果套接字没有断开并且没有错误,那么套接字连接或数据流发生了什么?

在另一端,(服务器端,数据发送者)似乎正在连续流式传输数据,而客户端(nodejs应用程序)已停止接收数据。

1 个答案:

答案 0 :(得分:2)

此问题是由于您使用管道机制回送了在原始端从未使用过的数据(通信是单向的)而引起的:

sock.pipe(sock);

这使您的代码可以作为回显服务器。您的套接字“套接字”是双工流(即,对于接收到的传入数据来说是可读的,对于发送回的传出数据都是可写的)。

如果您不需要回复,而只需要接收数据,一个快速解决方法是只需删除“ sock.pipe(sock);”即可。行。要了解说明,请先阅读。

很可能您的数据源(您提到的MT5应用程序)连续发送数据,并且根本不读取您发送回的内容。因此,您的代码将使用sock.pipe(sock)不断回显接收到的数据,填充从未使用过的传出缓冲区。但是,Nodejs流的管道机制处理反压,这意味着当两个流(可读和可写流)通过管道连接时,如果传出缓冲区正在填充(达到高水位标记) ,可读流将暂停,以防止可写流“溢出”。

您可以在Nodejs docs中了解有关背压的更多信息。该片段特别描述了流如何处理背压:

  

在Node.js中,源是可读流,而使用者是可写流[...]

     

触发背压的时刻可以精确地缩小到Writable .write()函数的返回值。 [...]

     

在任何情况下,如果数据缓冲区超出highWaterMark或写队列正忙,.write()将返回false。

     

返回错误值时,反压系统将启动。它将暂停传入的Readable流发送任何数据,并等待直到使用者再次准备就绪。

在下面,您可以找到我的设置,以显示反压的作用位置;有两个文件,server.js和client.js。如果同时运行它们,服务器将很快写入控制台“ BACKPRESSURE”。由于服务器未处理背压(它忽略了sock.write在某个时候开始返回false),因此将填充并填充传出缓冲区,从而占用更多内存,而在您的方案中,socket.pipe正在处理背压,因此暂停了传入消息流。

服务器:

// ----------------------------------------
// server.js

var net = require('net');

var server = net.createServer(function (socket) {
    console.log('new connection');

    // socket.pipe(socket); // replaced with socket.write on each 'data' event

    socket.setEncoding('utf8');
    socket.setKeepAlive(true);

    socket.on("data", function (d) {
        console.log("received: ", d);
        var result = socket.write(d);
        console.log(result ? 'write ok' : 'BACKPRESSURE');
    });

    socket.on('error', function (err) {
        console.log('client error:', err);
    });

    socket.on('end', function () {
        console.log('client disconnected');
    });
});

server.listen(10777, '127.0.0.1', () => {
    console.log('server listening...');
});

客户:

// ----------------------------------------
// client.js

var net = require('net');

var client = net.createConnection(10777, () => {
    console.log('connected to server!' + new Date().toISOString());

    var count = 1;
    var date;
    while(count < 35000) {
        count++;

        date = new Date().toISOString() + '_' + count;
        console.log('sending: ', date);
        client.write(date + '\n');
    }
});

client.on('data', (data) => {
    console.log('received:', data.toString());
});
client.on('end', () => {
    console.log('disconnected from server');
});