2012-04-01 30 views
15

Tôi cố gắng để sử dụng Node.js's ReadLine với a socket, như vậy:Node.js ReadLine không chờ đợi một dòng đầy đủ trên các kết nối 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); 

Khi tôi telnet vào cổng 7001 và bắt đầu gõ văn bản, nó ngay lập tức được lặp lại với tôi trước khi tôi đẩy vào.

Tại sao ReadLine không đợi toàn bộ dòng?

Tôi cũng đã thử .question() và tôi nhận được kết quả tương tự ... Cuộc gọi lại được kích hoạt khi nhận bất kỳ dữ liệu nào mà không phải đợi ký tự kết thúc.


Chỉnh sửa: Điều này trở nên xa lạ hơn. Khi tôi thử nghiệm bằng ứng dụng khách telnet của Windows, tôi nhận được hành vi mà tôi đã nói ở trên. Tuy nhiên, nếu tôi thử nghiệm sử dụng PuTTY làm ứng dụng khách, ReadLine hoạt động, ngay cả trên Windows. Tôi đã chụp một số gói. Có lẽ ai đó có thể làm sáng tỏ điều này? Các dòng không liên quan là dữ liệu từ máy khách. Dòng thụt lề là máy chủ trả lời.

Sử dụng 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           .. 

Sử dụng 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

Dường như các tài liệu hướng dẫn đồng ý với bạn về cách thức hoạt động của nó. Lỗi có thể xảy ra? Hoặc có lẽ nó chỉ hoạt động trên một số loại tay cầm. –

+0

@ David-SkyMesh, Vâng, tôi hy vọng rằng không phải như vậy, nhưng nghĩ rằng nó có thể là vậy. Tôi cũng chỉ tìm thấy bài đăng này trên Google Groups có vẻ liên quan: http://groups.google.com/group/nodejs/browse_thread/thread/1be5aa3dbf114eb5/dabc636270a61d52?show_docid=dabc636270a61d52 – Brad

+0

Chỉ cần thử ví dụ của bạn. Nó hoạt động hoàn hảo như mong đợi đối với tôi. – cababunga

Trả lời

16

Đây là một lỗi trong Node.js, giao diện ReadLine của gọi _normalWrite() trên mỗi sự kiện 'dữ liệu' và _normaWrite có một nhận xét rằng nó nên cố gắng để phá vỡ trên dòng mới, nhưng hiện tại nó just calls _onLine().

cái gì đó dọc theo dòng này nên sửa chữa nó cho bạn:

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

tôi đã không kiểm tra này, nó có thể cần phải thực hiện \r vào tài khoản cũng có. Xin vui lòng cho tôi biết nếu nó làm việc cho bạn, nếu như vậy thì một trong số chúng ta nên gửi một yêu cầu kéo với nó.

+0

Điều đó hiệu quả! Cảm ơn. Tôi vừa thực hiện một vài thay đổi nhỏ đối với mã của bạn. Tôi đã chỉnh sửa bài đăng của bạn để phản ánh những thay đổi đó. Bạn có phiền khi gửi yêu cầu kéo không? Tôi chưa thiết lập tài khoản Github. (Chỉ cần Bitbucket vào lúc này.) Cảm ơn một lần nữa !! – Brad

+0

Chắc chắn, tôi sẽ làm. Rất vui khi nó hoạt động cho bạn: D –

+1

Đây là yêu cầu kéo - khi đã được hợp nhất và phát hành, bạn sẽ có thể xóa bản hack đó :) https://github.com/joyent/node/pull/3059 –

5

Giải pháp thay thế cho sự cố của tôi ... Tôi chỉ cần có một số sự kiện dòng mỗi khi có một dòng mới từ luồng. Vì tôi không cần mọi thứ khác mà đi kèm với readline, tôi thấy đoạn này bằng cách TooTallNate đây: 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) 
    } 
    }) 
} 

này đã được đăng dưới dạng một comment để yêu cầu kéo Nathan ở đây: https://github.com/joyent/node/pull/3059

+0

hoàn toàn không liên quan, nhưng tôi chưa bao giờ thấy 'while (~ n)'. Đó là thiên tài. – Flonk

Các vấn đề liên quan