2

HTTP Chunked Transfer エンコーディングでストリーミング データを受信する小さな Ruby スクリプトを作成しようとしています。だから私はこれのクライアント側でルビーを使用しています。Ruby (および Rails) がストリームを提供することに関する多くの質問と情報を見つけることができますが、それらを消費することについてはあまり知りません。おそらくそれは些細なことであり、HTTP の低レベルの機能として機能するはずだからです。誰かが私に小さなサンプル スクリプトをくれませんか?

私はいくつかのことを試しました。これはopen-uriを使用しています:

require 'open-uri'

streamURL = 'http://localhost/sample-stream.php'

puts "Opening"

open(streamURL) do |f| 
   puts "Opening steam " + streamURL + " (never gets here)"
   p  f.meta
   p "Content-Type: " + f.content_type
   p "last modified" + f.last_modified.to_s

   no = 1
   # print the first three lines
   f.each do |line|
      print "#{no}: #{line}"
      no += 1
      break if no > 4
   end
end

...そしてこれは net http を使用しています:

require 'net/http'
require 'uri'

streamURL = 'http://localhost/sample-stream.php'

url = URI.parse(streamURL)
full_path = (url.query.empty?) ? url.path : "#{url.path}?#{url.query}"

the_request = Net::HTTP::Get.new(full_path, {'Transfer-Encoding' => 'chunked', 'content-type' => 'text/plain'})
#(Side question: Does it even make sense to specify 'chunked' in the request?)

puts "Opening stream " + streamURL

the_response = Net::HTTP.start(url.host, url.port) { |http|
  http.request(the_request)
}

puts the_response.body #never gets here

どちらの場合も、何も出力されません。Apache で、私の php スクリプトが忙しく、ますます多くのデータを吐き出していることがわかります。ここで何が問題なのかは明らかだと思います。どちらの場合も、スクリプトは処理する前に応答全体を取得するのを待っていると思います (これは決して起こりません)。

私のphpスクリプト(サーバー)に何か問題がある可能性があることに言及する必要がありますが、それがFirefoxにかなりうまくチャンクを吹き込んでいるのを見ることができます.

では、データをストリーミングする簡単なルビーの方法はありますか? または、これを行うには特別な宝石/ライブラリが必要になると予想する必要がありますか? (たとえば、このライブラリに出くわしました)

4

3 に答える 3

2

次のコードが機能するはずです。

require 'net/http'

streamURL = 'http://localhost/sample-stream.php'

uri = URI.parse(streamURL)

Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new uri.request_uri

  http.request request do |response|
    response.read_body do |chunk|
       #We get the data here chunk-by-chunk
       puts chunk
    end
  end
end

実際、これは私のsample-stream.phpでは機能しませんが、別のサーバーを指しているこのスクリプトに似たもので運が良かったです。認証も必要なため、作業コードはより複雑でしたが、ここでは少し削除しました。

私のテストphpスクリプトを指すと、このコードはやや役立つエラーメッセージになります。

`read_chunked': wrong chunk size line: (Net::HTTPBadResponse)

...これは、PHPサーバーの最後で何か間違ったことをしていることを明確に示しています。何が悪いのかわかりませんが、それは別の質問です。

于 2012-05-14T12:50:00.803 に答える
-1

'wget'システムコマンドを呼び出す別のアプローチ。

wget_command = "wget #{streamURL} --user=myusername --password=mypassword -qO-"

puts "Opening stream: #{wget_command}"
f = open("|" + wget_command)
  while (line = f.gets)
    puts "LINE:" + line  
  end #(loops forever)
end

これは、最初はrubyのネットhttpを使用するよりも信頼性が高いように見え、確かによりコンパクトなコードです。追加のボーナスとして、データを1行ずつ簡単に取得できます(チャンク読み取りアプローチから推測しなければならなかったもの)。欠点が何であるかはよくわかりません。この方法でstdoutデータをパイプすることにはおそらく非効率性があります。また、このコードはwgetコマンド(Windows)がないプラットフォームでは機能しませんが、私にとっては、これはネットhttp...よりも少しうまく機能するように見えました。

ただし、3〜4分経ってもまだ問題が発生しています。これは、ストリームの着信が速すぎてどこかのバッファがいっぱいになっているためか、この特定のストリームが数分後に遅くなるためだと思います(理由は聞かないでください。そうなるだけです)。最終的に追いつくとエラーが発生します。

于 2012-05-29T11:09:39.047 に答える