【问题标题】:Node net data merge when multiple write多次写入时节点网络数据合并
【发布时间】:2021-10-03 22:41:44
【问题描述】:

我正在使用 Node 网络。

客户端多次写入feed时,在服务端收到1条数据。

var net           = require('net');

// SERVER SIDE
var net_port   = 8080; // node net port
var server = net.createServer(function(connection){
   connection.on('data', function(data){
          var str = data.toString();
          console.log("Received, Length: "+str.length); // IT SHOULD be 25 in length
    });
   connection.pipe(connection);
});

server.listen(net_port, function() { 
   console.log('server is listening');
});
// SERVER CODE NED

// ### 客户端

var client = net.connect({port: 8080}, function() {
   console.log('connected to server!');  
});


string = "acdefghijklmnopqrstuvwxyz"; // 25 char
setInterval(function(){
    client.write(string);
    client.write(string);
},1);
setInterval(function(){
    client.write(string);
    client.write(string);
},1);

发送长度为 25 的字符串,但收到时 OUTPUT IS

Received, Length: 25
Received, Length: 25
Received, Length: 75  // merged 3 data
Received, Length: 100 // merged 4 data
Received, Length: 25
Received, Length: 50 // merge 2 times
Received, Length: 75
Received, Length: 25
Received, Length: 25
Received, Length: 25
Received, Length: 100

实际上,在我的实际代码中,我不能使用 split 字符串,因为如果客户端发送String length 100 4 次。所以服务器收到了

Received, Length: 100
Received, Length: 220
Received, Length: 80

如何强制 Node Net 发送和接收实际数据。

小提琴:https://www.mycompiler.io/view/BJGjA87

【问题讨论】:

    标签: node.js sockets


    【解决方案1】:

    net.createServer 创建一个 TCP 服务器。 TCP 套接字是基于流的,而不是基于数据报的。他们没有消息边界的概念:一切都只是一个连续的字节流,没有标记来区分哪些片段是一起发送的,哪些是单独发送的。如果您想在通过 TCP 套接字发送的消息之间建立边界,您必须自己划定它们:或者通过假设每条消息必须具有以字节为单位的固定长度,或者通过引入确定一条消息结束位置和另一条消息开始位置的标记。

    例如,下面是对您的服务器的简单修改,它为此使用RFC 7464 中定义的 json-seq 格式。从长远来看,您可能会考虑使用诸如ws 之类的库将其设为 WebSocket 服务器。它可能比下面的代码更健壮;这主要只是一个演示。

    var net = require('net');
    
    var server = net.createServer(function (connection) {
        var buffer = '';
        
        function receivedMessage(value) {
            console.log('received: ' + JSON.stringify(value));
        }
        
        function protocolError() {
            console.log('protocol error');
            connection.close();
        }
        
        function parseMessages(buf) {
            console.log('parsing ' + buf.length + ' code units worth of messages');
            if (buf.substring(0, 1) !== '\x1e') {
                protocolError();
                return;
            }
            var m, rx = /\x1e([^\x1e]*)/g;
            while (m = rx.exec(buffer)) {
                if (m[1] === '')
                    continue;
                try {
                    var value = JSON.parse(m[1]);
                } catch (e) {
                    if (e instanceof SyntaxError)
                        continue;   // RFC 7464 §2.3
                    throw e;
                }
                receivedMessage(value);
            }       
        }
        
        connection.on('data', function (data) {
            buffer += data.toString('utf8');
            console.log(buffer.length + ' code units in the buffer');
            var lastRS = buffer.lastIndexOf('\x1e');
            if (lastRS === 0)
                return;
            var fullMessages = buffer.substring(0, lastRS);
            buffer = buffer.substring(lastRS, buffer.length);
            parseMessages(fullMessages);
            try {
                var value = JSON.parse(buffer);
            } catch (e) {
                if (e instanceof SyntaxError)
                    return;  // maybe just truncated; defer error until later
                throw e;
            }
            receivedMessage(value);
            buffer = '';
        });
    
        connection.on('close', function () {
            console.log('closed');
            parseMessages(buffer);
        });
    });
    
    server.listen(8080, function() { 
        console.log('server is listening');
    });
    

    这是一个经过适当修改的客户端:

    var net = require('net');
    
    var client = net.connect({port: 8080}, function() {
       console.log('connected to server!');  
    });
    
    function sendMessage(value) {
        client.write(Buffer.from('\x1e' + JSON.stringify(value) + '\n', 'utf8'));
    }
    
    string = 'acdefghijklmnopqrstuvwxyz';
    
    setInterval(function(){
        sendMessage(string);
        sendMessage(string);
    }, 1);
    
    setInterval(function(){
        sendMessage(string);
        sendMessage(string);
    }, 1);
    

    【讨论】:

    • 我已经在使用它了,正如我所说的,有时数据是 1 个响应的一半,比如这里的“buffer = buffer.substring(lastRS);”它有时会产生错误,长期运行时会丢失一些字节。
    • 也为了我的应用程序的持久性,我不想在这条线上信任,这就是为什么我在每条消息中寻找正确的数据,比如在 socket.io 支持中。
    • 我发送字符串 = "start"+actual_value+"end";当 end 不包含它的平均值时,数据是一半,所以我将它与下一个响应连接起来,但它仍然会在长期内产生问题。
    猜你喜欢
    • 1970-01-01
    • 2021-12-06
    • 2020-06-06
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    相关资源
    最近更新 更多