web-dev-qa-db-ja.com

Node.jsを使用したデータのストリーミング

Node.jsを使用してサーバーからクライアントにデータをストリーミングできるかどうかを知りたいです。 Node.jsに単一のAJAX要求を送信し、接続を開いたままクライアントにデータを継続的にストリーミングします。クライアントはこのストリームを受信し、ページを継続的に更新します。

更新:

この回答 の更新として-これを機能させることはできません。 _response.write_は、closeを呼び出す前に送信されません。これを実現するために使用するサンプルプログラムを設定しました。

Node.js:

_var sys = require('sys'), 
http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    var currentTime = new Date();
    setInterval(function(){
        res.write(
            currentTime.getHours()
            + ':' + 
            currentTime.getMinutes()
            + ':' +
            currentTime.getSeconds()
        );
    },1000);
}).listen(8000);
_

HTML:

_<html>
    <head>
        <title>Testnode</title>
    </head>

    <body>
        <!-- This fields needs to be updated -->
        Server time: <span id="time">&nbsp;</span>

        <!-- import jQuery from google -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

        <!-- import jQuery -->
        <script type="text/javascript">
            $(document).ready(function(){
            // I call here node.localhost nginx ports this to port 8000
                $('#time').load('http://node.localhost');
            });
        </script>
    </body>
</html>
_

このメソッドを使用すると、close()を呼び出すまで何も返されません。これは可能ですか、それとも代わりにロード関数を呼び出して、長いポーリングアプローチを使用する必要がありますか?

41
Saif Bechan

可能です。 response.write ()を複数回使用するだけです。

var body = ["hello world", "early morning", "richard stallman", "chunky bacon"];
// send headers
response.writeHead(200, {
  "Content-Type": "text/plain"
});

// send data in chunks
for (piece in body) {
    response.write(body[piece], "ascii");
}

// close connection
response.end();

30秒ごとに接続を閉じて再度開く必要がある場合があります。

[〜#〜] edit [〜#〜]:これは実際にテストしたコードです:

var sys = require('sys'),
http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    var currentTime = new Date();
    sys.puts('Starting sending time');
    setInterval(function(){
        res.write(
            currentTime.getHours()
            + ':' +
            currentTime.getMinutes()
            + ':' +
            currentTime.getSeconds() + "\n"
        );

        setTimeout(function() {
            res.end();
        }, 10000);

    },1000);
}).listen(8090, '192.168.175.128');

Telnetで接続すると、実際にチャンク応答が返されます。しかし、AJAXブラウザはXHR.readyState = 3(部分応答)をサポートする必要があります。私の知る限り、すべてのブラウザがこれをサポートしているわけではありません。 Chrome/Firefoxの場合)。

EDIT2:また、ノードへのリバースプロキシとしてnginxを使用する場合、すべてのチャンクを収集してユーザーに一度に送信したい場合があります。微調整する必要があります。

25
Kuroki Kaze

Sockets.ioを見てください。 HTTP/HTTPSストリーミングを提供し、そのためにさまざまなトランスポートを使用します。

  • WebSocket
  • WebSocket over Flash(+ XMLセキュリティポリシーサポート)
  • XHRポーリング
  • XHRマルチパートストリーミング
  • Forever Iframe
  • JSONPポーリング(クロスドメイン用)

そして! Node.JSとシームレスに連携します。 NPMパッケージでもあります。

https://github.com/LearnBoost/Socket.IO

https://github.com/LearnBoost/Socket.IO-node

16
BMiner

無限ループを中止することもできます:

app.get('/sse/events', function(req, res) {
    res.header('Content-Type', 'text/event-stream');

    var interval_id = setInterval(function() {
        res.write("some data");
    }, 50);

    req.socket.on('close', function() {
        clearInterval(interval_id);
    }); 
}); 

これはexpressjsの例です。 expressjsがなければ、次のようなものになると思います。

4
Andrey Antukh