2

我正在尝试制作一个小红宝石脚本,它使用 HTTP 块传输编码接收流数据。所以我在这个客户端使用红宝石。我可以找到很多关于 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。

那么有没有一种简单的 ruby​​ 方法来流式传输数据?还是我应该期望需要特殊的宝石/库来做到这一点?(例如,我遇到了这个库

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 回答
0

我尝试了先前答案(Net::HTTP.startwget)中的方法,但没有得到任何输出。对我有用的是:

url = <...>
IO.popen "curl -s #{url}" do |io|
  io.sync = true
  io.each do |line|
    break if !(process_line line)
  end
end
于 2018-06-25T17:15:33.393 回答
-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​​ 的 net http 更可靠,而且它的代码肯定更紧凑。作为额外的奖励,我可以轻松地逐行获取数据(我不得不从块读取方法中捏造的其他东西)不太确定缺点是什么。以这种方式管道标准输出数据可能效率低下。此外,此代码不会在没有 wget 命令的平台上运行(Windows)但对我来说,这似乎比 net http 好一点...

但是,三四分钟后它仍然会遇到问题。我在想这要么是因为流来得太快,某个地方的缓冲区被填满,要么是因为这个特定的流在几分钟后变慢了(不要问我为什么。它就是这样),所以也许当它最终赶上时,错误就来了。

于 2012-05-29T11:09:39.047 回答