2012-03-23 100 views
1

我正在尝试使用HTTP分块传输编码接收流数据的小ruby脚本。所以我在客户端使用红宝石结束了。我可以找到很多有关红宝石(和导轨)服务流的问题和信息,但没有太多关于消费他们。也许是因为它很简单,应该只是作为HTTP的低级特性工作。那么有人可以给我一个小样本脚本?Ruby分块编码客户端

我尝试了几件事情。这一次使用开放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 

...而这一次使用网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方式来传输数据?或者我应该期望需要特殊的宝石/库来做到这一点? (我碰到例如this library

回答

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 

其实这不适合我的样本stream.php工作,但我曾与类似这样的脚本运气的东西,在另一台服务器指向。我的工作代码更复杂,因为它也需要验证,但我已经在这里简化了一下。

在我测试的PHP脚本指点,这个代码导致有些有用的错误消息:

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

...这清楚地表明我做错了的事情PHP服务器端。不知道什么是错的,但那是另一个问题。

+0

附加说明:我遇到了这个奇怪的问题。它高兴地消耗流三到四分钟,然后开始注入\ n2000 \ n定期到流中。也许这就是我看到的块大小,除了它们似乎不对应块的开始或结束。当然,我不期望看到任何协议级别的东西。很显然,这些2000行对于我正在尝试解析的内容大打折扣。使用wget我没有看到同样的问题,所以一定是在红宝石网的HTTP错误?想知道是否有人遇到同样的问题。 – 2012-05-28 13:22:55

+0

作为更新...我看到这是因为脚本跟不上流。当我写入memcache而不是数据库时解决。我很惊讶,我没有得到更有用的“缓冲区满”例外。所以我想这是需要注意的。 – 2013-02-28 16:35:37

-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更可靠,而且它肯定是更紧凑的代码。作为额外的好处,我可以很容易地逐行获取数据(我从块阅读方法中得到的其他东西)我不确定这些缺点是什么。以这种方式管理标准输出数据可能效率低下。此外,这段代码不会在没有wget命令的平台上工作(windows)但是对我来说,这看起来好像比网络http好一点...

但是它在三四分钟后仍然出现问题。我想象这是因为流速过快,某处的某个缓冲区被填满,或者因为这个特定的流会在几分钟后减慢(不要问我为什么,它只是),所以也许当它终于迎头赶上时,就会出现错误。

+0

注意! [你在玩火](http://sakurity.com/blog/2015/02/28/openuri.html) – Ich 2015-06-16 09:21:14