Ruby,Telnet,无需超时即可读取多行响应

时间:2016-02-19 16:17:24

标签: ruby json telnet

我需要一些提示/帮助,如何将多行响应读入变量。 我当前的命令导致多线响应但在此之后我得到超时。

以下是我的连接设置方式:

connection = Net::Telnet.new('Host' => host,'Port' => 4800, 'Telnetmode' => false, 'Timeout' => 1)

这是我的要求以及如何保存它:

puts "Weather request\n"
connection.cmd("{weather}"){ |c| print c }
parsed = JSON.parse(str)
puts "#{parsed}\n\n"

这就是错误:

/usr/lib/ruby/1.9.1/net/telnet.rb:558:in `waitfor': timed out while waiting for more data (Timeout::Error)
    from /usr/lib/ruby/1.9.1/net/telnet.rb:695:in `cmd'
    from ruby_check.rb:37:in `<main>'

我的回答是多条JSON行,如下所示:

{"City":"Tallinn", "Degrees":"23"}
{"City":"Berlin", "Degrees":"23"}
{"City":"Helsinki", "Degrees":"23"}
{"City":"Stockholm", "Degrees":"23"}

2 个答案:

答案 0 :(得分:2)

为什么超时?

Net::Telnet documentation说:

  

对于某些协议,可以在创建Telnet对象并使用cmd()调用时指定一次“提示”选项;对于其他人,您必须指定响应序列以查找每个cmd()调用的匹配选项,或直接调用puts()和waitfor();对于其他人,你将不得不使用sysread()而不是waitfor()并自己解析服务器响应。

当与Net::Telnet#cmd method's documentation结合使用时更有意义,TCPSocket表示方法:

  

向主机发送一个字符串,并读入所有收到的数据,直到看到提示或其他匹配的序列。

您未指定自定义PromptMatch选项,因此#cmd正在等待服务器中与默认Net::Telnet提示符匹配的内容({ {1}})表示消息的结束。 如果消息没有以这种提示结束,那么它将永远等待。

可能的解决方案

匹配服务器的提示

如果服务器确实发送某种提示以表明它已完成发送数据,您应该键入下一个命令,则可以将与其匹配的正则表达式传递给/[$%#>] \z/n初始化程序。例如,如果服务器提示您Net::Telnet,则可以使用:

command:

匹配响应的结尾

如果没有提示,但您正在等待特定字符序列的响应,则可以在致电connection = Net::Telnet.new( "Prompt" => /command: \z/, # … ) 时明确指定Match选项。例如,如果您的响应是单个JSON数组,那么它将以#cmd结束,因此您可以使用它:

]

放弃connection.cmd("String" => "{weather}", "Match" => "]") { |c| print c } 并使用Net::Telnet

如果没有提示且没有已知结尾,您可以尝试使用TCPSocket对象的基础here来读取数据而不使用Net::Telnet

#cmd

此时,使用connection.puts("{weather}") connection.sock.readline 优于普通Net::Telnet可能没什么好处。

答案 1 :(得分:1)

您将超时设置为一秒,并且不指定str是什么。您可以尝试增加超时值,甚至可以将其设置为false。 Believieng它是.cmd的结果,试试这个:

connection = Net::Telnet.new(
  "Host" => host, "Port" => 4800, 
  "Telnetmode" => false, "Timeout" => false)

puts "Weather request...\n"

str = connection.cmd("{weather}"){ |c| print c }
parsed = JSON.parse(str)

puts "#{parsed}\n\n"