2012-04-01 5 views
15

Ich versuche Node.js's ReadLine mit a socket zu verwenden, etwa so:Node.js ReadLine nicht auf eine vollständige Zeile auf Socket-Verbindungen warten?

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); 

Wenn ich in Port 7001 Telnet und starten Sie Text eingeben, wird es sofort wieder zu mir wider, bevor ich jemals betreten drücken.

Warum wartet ReadLine nicht auf eine vollständige Zeile?

Ich habe auch versucht .question() und ich bekomme die gleichen Ergebnisse ... Der Rückruf wird beim Empfang von Daten ausgelöst, ohne auf ein Ende der Zeile Zeichen zu warten.


Edit: Dies wird noch seltsamer. Wenn ich den Windows-Telnet-Client verwende, erhalte ich das oben angegebene Verhalten. Wenn ich jedoch PuTTY als Client verwende, funktioniert ReadLine auch unter Windows. Ich habe einige Päckchen gemacht. Vielleicht könnte jemand etwas Licht ins Dunkel bringen? Nicht eingerückte Zeilen sind Daten vom Client. Eingerückte Zeilen sind die Antworten des Servers.

Windows-Telnet Mit

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           .. 

mit 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

Es ist wie die Dokumentation sieht stimmt mit Ihnen überein, wie es funktionieren soll. Möglicher Fehler? Oder vielleicht funktioniert es nur bei bestimmten Arten von Griffen. –

+0

@ David-SkyMesh, Ja, ich hoffe, dass das nicht der Fall ist, aber denke, dass es wahrscheinlich ist. Ich habe diesen Beitrag auch in Google Groups gefunden, der ähnlich aussieht: http://groups.google.com/group/nodejs/browse_thread/thread/1be5aa3dbf114eb5/dabc636270a61d52?show_docid=dabc636270a61d52 – Brad

+0

Ich habe Ihr Beispiel versucht. Es funktioniert perfekt wie erwartet für mich. – cababunga

Antwort

16

Dies ist ein Fehler in node.js ist, Readline die Schnittstelle ruft _normalWrite() auf jeder 'Daten' Ereignis und _normaWrite hat einen Kommentar, dass es versuchen sollte, Newline zu brechen, aber derzeit just calls _onLine().

Etwas nach dem Vorbild dafür sollte es für Sie beheben:

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); 
    } 
}; 

ich nicht getestet haben, kann es müssen auch \r berücksichtigen. Bitte lassen Sie es mich wissen, wenn es für Sie funktioniert, wenn ja, dann sollte einer von uns Knoten eine Pull-Anfrage damit senden.

+0

Das hat super funktioniert! Vielen Dank. Ich habe nur ein paar kleine Änderungen an Ihrem Code vorgenommen. Ich habe Ihren Beitrag bearbeitet, um diese Änderungen widerzuspiegeln. Würde es Ihnen etwas ausmachen, eine Pull-Anfrage einzureichen? Ich habe kein Github-Konto eingerichtet. (Just Bitbucket im Moment.) Danke nochmal !! – Brad

+0

Sicher, ich werde es tun. Froh, dass es für dich funktioniert: D –

+1

Hier ist die Pull-Anfrage - sobald das zusammengeführt und freigegeben wird, können Sie diesen Hack entfernen :) https://github.com/joyent/node/pull/3059 –

5

Eine alternative Lösung für mein Problem ... Ich musste nur jedesmal ein Line-Event bekommen, wenn eine neue Zeile aus einem Stream kam. Da ich nicht alles andere, was mit Readline- kommt brauchte, fand ich diese Schnipsel von TooTallNate hier: 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) 
    } 
    }) 
} 

Dies wurde als Kommentar zu Nathans-Pull-Request hier gepostet: https://github.com/joyent/node/pull/3059

+0

völlig unabhängig, aber ich habe 'while (~ n)' nie gesehen. Das ist Genie. – Flonk

Verwandte Themen