1

我正在尝试使用带有 ruby​​ eventmachine 的 HTML5 websocket 编写一个 web telnet 客户端。但是当 EM.watch 尝试监视新创建的 Net::Telnet 实例时它失败了。以下是服务器端和客户端代码:

服务器端:

require 'em-websocket'
require "debugger"
require 'net/telnet'


class Foo < EM::Connection
  def initialize(websocket)
    @websocket = websocket
    @alltext = ""
  end


  def notify_readable
        header= @io.recvfrom(2000)[0].chomp
        header2 = header.to_s.encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => "s")
        if header2.length ==1 
             @alltext = @alltext + header2
        else 
            @alltext.each_line do |x| 
                 $stdout.puts x
                 @websocket.send x
            end

           @alltext = ""
           header2.to_s.each_line do |y|
                $stdout.puts y
                @websocket.send  y
            end
        end

        if header == "\r\n"
           fd = detach
        end
        rescue EOFError
              detach
  end

def unbind
    EM.next_tick do

    end
    puts "close the socket:" + @io.to_s
end
end


EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8090) do |ws|
      ws.onopen    { 
                puts "Web socket is opened"
                ws.send "terminal to the node"
                          nodeSocket = Net::Telnet::new("Host" => "10.4.0.50","Timeout" => 10,"Prompt" => /login/ )
                          puts nodeSocket
                nodeSocket.cmd("username") { |c| print c}
                nodeSocket.cmd("password") { |c| print c}

                           EM.run{
                          $conn = EM.watch nodeSocket,Foo,ws
                           $conn.notify_readable = true
                 }

      }

      ws.onmessage { |msg| 
                puts msg
                ws.send msg
      }


      ws.onclose   { 
            puts "WebSocket closed" 
      }
end

克林特方面:

require 'eventmachine'
require 'em-http-request'

EventMachine.run {
  http = EventMachine::HttpRequest.new("ws://localhost:8090").get :timeout => 0
  http.errback { puts "oops" }
  http.callback {
  puts "WebSocket connected!"
  http.send("Hello client")
 }

http.stream { |msg|
   puts "Recieved: #{msg}"

 }
}

服务器端日志

C:\Ruby193\bin>ruby websocketserver12.rb
Web socket is opened
#<Net::Telnet:0xf976e0>
------------------Welcome to syseng1--------------------
This machine is the Server
--------------------------------------------------------
Ubuntu 8.04.3 LTS
syseng1 login: username
Password:
Last login: Tue Jun  5 15:05:00 EDT 2012 from 358.ystems.com on pts/0
Linux syseng1 2.6.24-24-generic #1 SMP Fri Jul 24 22:46:06 UTC 2009 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
You have mail.
←[01;32musername@syseng1 ←[01;34m~ $ ←[00mWebSocket closed
C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-    mingw32/lib/eventmachine.rb:735:in `attach_fd': can't convert Net::Telnet into Integer (TypeError)
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:735:in `attach_io'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:708:in `watch'
    from websocketserver12.rb:57:in `block (3 levels) in <main>'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:163:in `call'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:163:in `run'
    from websocketserver12.rb:56:in `block (2 levels) in <main>'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/connection.rb:20:in `call'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/connection.rb:20:in `trigger_on_open'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/handler.rb:18:in `run'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/connection.rb:114:in `dispatch'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/connection.rb:71:in `receive_data'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:179:in `run_machine'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/eventmachine-1.0.0.beta.4.1-x86-mingw32/lib/eventmachine.rb:179:in `run'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/em-websocket-0.3.6/lib/em-websocket/websocket.rb:9:in `start'
    from websocketserver12.rb:47:in `<main>'

看起来 EM.watch 无法观看 Net::Telnet::new 实例,因为它无法将文件句柄转换为 lib 中某处的 Integer。我用 EM.watch 尝试了同样的事情来观察 TCPSocket,这个事件机器工作得很好。以前有人有同样的问题吗?

4

1 回答 1

1

引发错误in `attach_fd': can't convert Net::Telnet into Integer (TypeError)是因为 Eventmachine.watch() “使用 eventloop 注册给定的文件描述符或 IO 对象”,而 Net::Telnet 实例不是这些。

根据 Net::Telnet文档,Net::Telnet 实例的 sock 属性是指实例使用的套接字。所以你可以将它传递给 EventMachine.watch() 方法。

于 2015-07-23T20:38:05.170 回答