【问题标题】:Node.js ReadLine not waiting for a full line on socket connections?Node.js ReadLine 不等待套接字连接的完整行?
【发布时间】:2012-04-15 06:33:33
【问题描述】:

我正在尝试将Node.js's ReadLinea socket 一起使用,如下所示:

var net = require('net');
var rl = require('readline');

this.streamServer = net.createServer(function (socket) {
    var i = rl.createInterface(socket, socket);
    i.on('line', function (line) {
        socket.write(line);
    });
});
this.streamServer.maxConnections = 1;
this.streamServer.listen(7001);

当我 telnet 到端口 7001 并开始输入文本时,它会立即回显给我,然后再按回车键。

为什么 ReadLine 没有等待整行?

我也尝试过.question(),得到了相同的结果...回调在接收到任何数据时触发,无需等待行尾字符。


编辑:这变得更奇怪了。当我使用 Windows telnet 客户端进行测试时,我得到了上述行为。但是,如果我使用 PuTTY 作为客户端进行测试,ReadLine 可以工作,即使在 Windows 上也是如此。我做了一些数据包捕获。也许有人可以对此有所了解?未缩进的行是来自客户端的数据。缩进的行是服务器回复。

使用 Windows Telnet

00000000  61                                               a
    00000000  61                                               a
00000001  62                                               b
    00000001  62                                               b
00000002  63                                               c
    00000002  63                                               c
00000003  64                                               d
    00000003  64                                               d
00000004  65                                               e
    00000004  65                                               e
00000005  66                                               f
    00000005  66                                               f
00000006  67                                               g
    00000006  67                                               g
00000007  68                                               h
    00000007  68                                               h
00000008  69                                               i
    00000008  69                                               i
00000009  6a                                               j
    00000009  6a                                               j
0000000A  6b                                               k
    0000000A  6b                                               k
0000000B  6c                                               l
    0000000B  6c                                               l
0000000C  6d                                               m
    0000000C  6d                                               m
0000000D  6e                                               n
    0000000D  6e                                               n
0000000E  6f                                               o
    0000000E  6f                                               o
0000000F  70                                               p
    0000000F  70                                               p
00000010  0d 0a                                            ..
    00000010  0d 0a                                            ..
00000012  0d 0a                                            ..
    00000012  0d 0a                                            ..
00000014  0d 0a                                            ..
    00000014  0d 0a                                            ..
00000016  61                                               a
    00000016  61                                               a
00000017  73                                               s
    00000017  73                                               s
00000018  64                                               d
    00000018  64                                               d
00000019  66                                               f
    00000019  66                                               f
0000001A  0d 0a                                            ..
    0000001A  0d 0a                                            ..
0000001C  61                                               a
    0000001C  61                                               a
0000001D  73                                               s
    0000001D  73                                               s
0000001E  64                                               d
    0000001E  64                                               d
0000001F  66                                               f
    0000001F  66                                               f
00000020  0d 0a                                            ..
    00000020  0d 0a                                            ..

使用 PuTTY

00000000  ff fb 1f ff fb 20 ff fb  18 ff fb 27 ff fd 01 ff ..... .. ...'....
00000010  fb 03 ff fd 03                                   .....
    00000000  ef bf bd ef bf bd 1f ef  bf bd ef bf bd 20 ef bf ........ ..... ..
    00000010  bd ef bf bd 18 ef bf bd  ef bf bd 27 ef bf bd ef ........ ...'....
    00000020  bf bd 01 ef bf bd ef bf  bd 03 ef bf bd ef bf bd ........ ........
    00000030  03                                               .
00000015  61 62 63 64 65 66 67                             abcdefg
0000001C  0d 0a                                            ..
    00000031  61 62 63 64 65 66 67                             abcdefg
    00000038  0d 0a                                            ..
0000001E  61 73 64 66                                      asdf
00000022  0d 0a                                            ..
    0000003A  61 73 64 66                                      asdf
    0000003E  0d 0a                                            ..
00000024  61 73 64 66                                      asdf
00000028  0d 0a                                            ..
    00000040  61 73 64 66                                      asdf
    00000044  0d 0a                                            ..
0000002A  0d 0a                                            ..
    00000046  0d 0a                                            ..

【问题讨论】:

  • 看起来文档与您同意它应该如何工作。可能的错误?或者它只适用于某些类型的句柄。
  • @David-SkyMesh,是的,我希望情况并非如此,但认为它可能是。我还刚刚在 Google 网上论坛上发现了这篇看起来相关的帖子:groups.google.com/group/nodejs/browse_thread/thread/…
  • 刚刚试过你的例子。它完全符合我的预期。
  • @cababunga,你运行什么版本的 Node.js?
  • @cababunga,什么操作系统?我在 Windows 下运行相同的版本。

标签: javascript node.js newline


【解决方案1】:

这是 node.js 中的一个错误,ReadLine 的接口在每个 'data' 事件上调用 _normalWrite() 并且 _normaWrite 有一条注释,它应该尝试在换行符处换行,但目前它是 just calls _onLine()

类似的东西应该会为你解决这个问题:

i._normalWrite = function(b) {
    if(b == undefined) {
        return;
    }
    if(!this._line_buffer) {
        this._line_buffer = '';
    }
    this._line_buffer += b.toString();
    if(this._line_buffer.indexOf('\n') !=-1 ) {
        var lines = this._line_buffer.split('\n');
        // either '' or the unfinished portion of the next line
        this._line_buffer = lines.pop();
        lines.forEach(function(line) {
            this._onLine(line + '\n');
        }, this);
    }
};

我没有对此进行测试,可能还需要考虑\r。请让我知道它是否适合您,如果适合,那么我们中的一个应该向节点发送拉取请求。

【讨论】:

  • 效果很好!谢谢。我只是对你的代码做了一些小的改动。我编辑了你的帖子以反映这些变化。你介意提交一个拉取请求吗?我没有设置 Github 帐户。 (目前只是 Bitbucket。)再次感谢!
  • 这是拉取请求 - 一旦合并并发布,您就可以删除该 hack :) github.com/joyent/node/pull/3059
  • 看起来不错,谢谢!明天早上,只要 Stack Overflow 允许我就 +200。
  • 太棒了,谢谢!这实际上标志着我对 node.js 核心的第一次贡献,所以我认为将我的 SO 分数提高近一倍是一个很好的庆祝方式:D
  • 感谢您提交修复 Nathan。您的 pull 已登陆并将在 v0.7.8 版本中。干杯!
【解决方案2】:

我的问题的另一种解决方案...每次流中有新行时,我只需要获取某种行事件。因为我不需要 readline 附带的所有其他东西,所以我在这里找到了 TooTallNate 的这个 sn-p:https://gist.github.com/1785026

/**
 * By TooTallNate, originally posted at https://gist.github.com/1785026
 * A quick little thingy that takes a Stream instance and makes
 * it emit 'line' events when a newline is encountered.
 *
 *   Usage:
 *   ‾‾‾‾‾
 *  emitLines(process.stdin)
 *  process.stdin.resume()
 *  process.stdin.setEncoding('utf8')
 *  process.stdin.on('line', function (line) {
 *    console.log(line event:', line)
 *  })
 *
 */

function emitLines (stream) {
  var backlog = ''
  stream.on('data', function (data) {
    backlog += data
    var n = backlog.indexOf('\n')
    // got a \n? emit one or more 'line' events
    while (~n) {
      stream.emit('line', backlog.substring(0, n))
      backlog = backlog.substring(n + 1)
      n = backlog.indexOf('\n')
    }
  })
  stream.on('end', function () {
    if (backlog) {
      stream.emit('line', backlog)
    }
  })
}

这是对 Nathan 的拉取请求的评论发布在这里:https://github.com/joyent/node/pull/3059

【讨论】:

  • 完全不相关,但我从未见过while (~n)。那是天才。
  • @Flonk while (n >= 0) 更具可读性,并且至少同样有效。
猜你喜欢
  • 1970-01-01
  • 2017-12-10
  • 2021-05-23
  • 1970-01-01
  • 2017-09-02
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多