Node.js ReadLine не ждет полной строки в соединениях сокета?

Я пытаюсь использовать Node.js ReadLine с сокет, например:

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() и получил те же результаты... Обратный вызов запускается при получении любых данных, не дожидаясь окончания -строчный символ.


Изменить: Это становится еще более странным. Когда я тестирую с помощью клиента telnet Windows, я получаю поведение, о котором я говорил выше. Однако, если я тестирую 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                                            ..

Ответы

Ответ 1

Это ошибка в node.js, интерфейс ReadLine вызывает _normalWrite() на каждом событии данных, а _normaWrite имеет комментарий, что он должен попытаться сломать строки новой строки, но в настоящее время он просто вызывает _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. Пожалуйста, дайте мне знать, если это сработает для вас, если это так, тогда один из нас должен отправить node запрос на перенос с ним.

Ответ 2

Альтернативное решение моей проблемы... Мне просто нужно было получить какое-то событие линии каждый раз, когда появилась новая строка из потока. Поскольку мне не нужно все, что поставляется с readline, я нашел этот фрагмент с помощью TooTallNate здесь: 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 pull здесь: https://github.com/joyent/node/pull/3059