在Ruby中访问循环外的对象/方法

时间:2015-12-03 19:03:44

标签: ruby sockets

我尝试访问此循环之外的对象/方法,以获取使用Ruby编码的简单HTTP服务器:

require 'socket'                # Get sockets from stdlib

class Hello
  def say_hi 
    "Hello, world!"
  end
end

hi = Hello.new
server = TCPServer.open(2000)   # Socket to listen on port 2000
loop {                          # Servers run forever
  Thread.start(server.accept) do |client|
    client.puts(hi.say_hi)
    client.close                # Disconnect from the client
  end
}

看起来请求只是挂起,因为" hi"及其" say_hi"方法不能在循环外访问。如何访问对象,模块和方法,以便将它们用于我的简单服务器?

2 个答案:

答案 0 :(得分:2)

它按预期工作。当你调用server.accept时它会阻塞等待客户端连接。您可以通过启动程序并远程登录来确认这一点,例如:

telnet localhost 2000
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello, world!
Connection closed by foreign host.

请注意,服务器以" Hello,world!"

回复

答案 1 :(得分:0)

您提供的示例代码运行正常。我能够运行服务器,通过telnet localhost 2000连接并接收" Hello,world!"连接关闭前的消息。

有时候某个区块无法访问其周围的本地范围。在您的示例中并非如此,但如果您在其他地方遇到此问题,则可以采取相应措施。

常量和全局变量在全局可见。您可以将Hello实例变量分配给全局:$hi = Hello.new,但大多数开发人员会告诉您使用全局变量是"坏"。您可以修改Hello类,使其包含实例注册表:

require 'socket'                # Get sockets from stdlib

class Hello
  def initialize(name)
    self.class.registry[name] = self
  end

  def say_hi 
    "Hello, world!"
  end

  def self.registry
    @@registry ||= {}
  end
end

Hello.new(:hi)
server = TCPServer.open(2000)   # Socket to listen on port 2000
loop {                          # Servers run forever
  Thread.start(server.accept) do |client|
    client.puts(Hello.registry[:hi].say_hi)
    client.close                # Disconnect from the client
  end
}

还有其他方法可以克服范围问题,包括将hi实例传递给Thread.start,使用thread local variables等。很难在提供的代码已经有效的情况下建议具体的内容。