NodeJS:处理TCP套接字流的正确方法是什么?我应该使用哪个分隔符?

时间:2011-08-12 00:39:59

标签: sockets node.js tcp stream buffer

根据我的理解here,“V8有一代分类垃圾收集器。随机移动对象。节点无法获取指向原始字符串数据的指针以写入套接字。”所以我不应该将来自TCP流的数据存储在字符串中,特别是如果该字符串变得大于Math.pow(2,16)字节。 (希望我到现在为止......)

那么处理来自TCP套接字的所有数据的最佳方法是什么?到目前为止,我一直在尝试使用_:_:_作为分隔符,因为我认为它在某种程度上是独特的,不会混淆其他东西。

将来的数据样本为something_:_:_maybe a large text_:_:_ maybe tons of lines_:_:_more and more data

这就是我试图做的事情:

net = require('net');
var server = net.createServer(function (socket) {
    socket.on('connect',function() {
        console.log('someone connected');
        buf = new Buffer(Math.pow(2,16));  //new buffer with size 2^16
        socket.on('data',function(data) {
            if (data.toString().search('_:_:_') === -1) {    // If there's no separator in the data that just arrived...
                buf.write(data.toString());   // ... write it on the buffer. it's part of another message that will come.
            } else {        // if there is a separator in the data that arrived
                parts = data.toString().split('_:_:_'); // the first part is the end of a previous message, the last part is the start of a message to be completed in the future. Parts between separators are independent messages
                if (parts.length == 2) {
                    msg = buf.toString('utf-8',0,4) + parts[0];
                    console.log('MSG: '+ msg);
                    buf = (new Buffer(Math.pow(2,16))).write(parts[1]);
                } else {
                    msg = buf.toString() + parts[0];
                    for (var i = 1; i <= parts.length -1; i++) {
                        if (i !== parts.length-1) {
                            msg = parts[i];
                            console.log('MSG: '+msg);
                        } else {
                            buf.write(parts[i]);
                        }
                    }
                }
            }
        });
    });
});

server.listen(9999);

每当我尝试console.log('MSG' + msg)时,它都会打印出整个缓冲区,所以查看是否有效是没用的。

如何以正确的方式处理这些数据?惰性模块是否可以工作,即使这些数据不是面向行的?是否有其他模块来处理非面向行的流?

2 个答案:

答案 0 :(得分:6)

确实有人说有额外的工作正在进行,因为Node必须接受该缓冲区,然后将其推入v8 /将其转换为字符串。但是,在缓冲区上执行toString()并不是更好。据我所知,目前还没有很好的解决方案,特别是如果你的最终目标是得到一个字符串并且愚弄它。它是Ryan提到@ nodeconf作为需要完成工作的领域之一。

至于分隔符,你可以选择你想要的任何东西。许多二进制协议选择包含一个固定的头,这样你就可以把东西放在一个普通的结构中,这很多次都包括一个长度。通过这种方式,您可以分割已知的标头并获取有关其余数据的信息,而无需迭代整个缓冲区。通过这样的方案,可以使用像:

这样的工具

另外,可以通过数组语法访问缓冲区,也可以使用.slice()将它们分开。

最后,请在此处查看:https://github.com/joyent/node/wiki/modules - 找到一个解析简单tcp协议的模块,似乎做得很好,并阅读了一些代码。

答案 1 :(得分:3)

您应该使用新的stream2 api。 http://nodejs.org/api/stream.html

以下是一些非常有用的示例:https://github.com/substack/stream-handbook

https://github.com/lvgithub/stick

相关问题