2012-04-01 2 views
15

Я пытаюсь использовать Node.js's ReadLine с a socket, например, так: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); 

Когда я телнет в порт 7001 и начните набирать текст, он немедленно возвращается обратно ко мне, прежде чем я когда-либо нажать ввод.

Почему ReadLine не ждет полной линии?

Я также пробовал .question(), и получаю те же результаты ... Обратный вызов запускается при получении любых данных, не дожидаясь конца строки.


Edit: Это становится еще более странным. Когда я тестирую с помощью клиента 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           .. 
+0

Это выглядит как документация соглашается с вами о том, как он должен работать. Возможная ошибка? Или, возможно, он работает только на определенных ручках. –

+0

@ David-SkyMesh, Да, я надеюсь, что это не так, но думаю, что это возможно. Я также нашел этот пост в Google Groups, который выглядит следующим образом: http://groups.google.com/group/nodejs/browse_thread/thread/1be5aa3dbf114eb5/dabc636270a61d52?show_docid=dabc636270a61d52 – Brad

+0

Просто попробовал ваш пример. Он работает отлично, как и ожидалось для меня. – cababunga

ответ

16

Это ошибка в Node.js, интерфейс Readline называет _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 во внимание также. Пожалуйста, дайте мне знать, если это сработает для вас, если это так, тогда один из нас должен отправить узел с запросом на перенос.

+0

Это сработало отлично! Благодарю. Я только что внес несколько незначительных изменений в ваш код. Я отредактировал ваше сообщение, чтобы отразить эти изменения. Не могли бы вы отправить запрос на тяну? У меня нет учетной записи Github. (Просто Битбакет в данный момент.) Еще раз спасибо! – Brad

+0

Конечно, я сделаю это. Рад, что это сработало для вас: D –

+1

Вот запрос на вытягивание - после того, как он будет объединен и выпущен, вы сможете удалить этот хак :) https://github.com/joyent/node/pull/3059 –

5

Альтернативное решение моей проблемы ... Мне просто нужно было получить какое-то событие линии каждый раз, когда появилась новая строка из потока. Поскольку мне не нужен все остальное, что происходит с 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) 
    } 
    }) 
} 

Это был опубликован в качестве комментария к тяговой запросу Натана здесь: https://github.com/joyent/node/pull/3059

+0

полностью не связан, но я никогда не видел 'while (~ n)'. Это гениально. – Flonk

Смежные вопросы