插座和/或赛璐珞:IO的正确使用



我有一个Pinoccio微控制器(绝对棒极了,试试吧)。微控制器打开其服务器的插座。我正在Ruby应用程序中编写TCP套接字服务器,我将在其中使用Celluloid::IO。作为我的指导,我在Node中跟踪这个实现,称为pinoccio服务器

我写了一些测试代码,试图与Pinoccio微控制器进行通信。我可以毫无问题地从中读取数据,但当我将数据写回套接字时,我永远不会得到我期望的行为。这是代码,有人能告诉我我是否滥用了赛璐珞:IO或套接字吗?

https://gist.github.com/roder/ab211f2f58ad6c90a3a9

当时如果有这个问题,语法是正确的。但现在不是,从Celluloid0.17.0开始。。。但这不是答案,这只是前言。我已经分叉并编辑了你的要点:

https://gist.github.com/digitalextremist/7dc74b03587cd4b3b7dd

以下是新的要点:

require 'celluloid/current'
require 'celluloid/io'
require 'json'
class TestServer
  include Celluloid::IO
  finalizer :shutdown
  def initialize(host, port)
    puts "*** Starting echo server on #{host}:#{port}"
    # Since we included Celluloid::IO, we're actually making a
    # Celluloid::IO::TCPServer here
    @server = TCPServer.new(host, port)
  end
  def shutdown
    @server.close rescue nil
  end
  def run
    loop {
      async.handle_connection(@server.accept)
    }
  end
  def handle_connection(socket)
    addr = *socket.peeraddr
    puts "*** Received connection from #{addr[3]}:#{addr[1]}"
    # This is just a test, followed this format:
    #  https://github.com/soldair/pinoccio-server/blob/master/troop.js#L163
    cmd = {
      :type => "command",
      :to => 1,
      :timeout => 10000,
      :command => "led.on"
    }
    json_cmd = "#{cmd.to_json}n"
    socket.write json_cmd # The light never turns on. Why?
    puts json_cmd
    loop {
      puts socket.readpartial(4096)
    }
  rescue EOFError
    puts "*** #{addr[3]}:#{addr[1]} disconnected"
  rescue => ex
    echo "Trouble with socket: [#{ex.class}] #{ex.message}"
  ensure
    socket.close rescue nil
  end
end
TestServer.supervise(as: :test_server, args: ["0.0.0.0", 1234])
#de Not needed. Killed by Celluloid.shutdown already...
#de trap("INT") { supervisor.terminate; exit }
#de Avoid starting the server in the constructor, then sleeping.
#de Could end up with a race condition, and/or botch instantiation.
#de But with that being said, you need to detect crashes... so:
loop {
  begin
    Celluloid[:test_server].run
  rescue => ex
    echo "Trouble with supervised server: [#{ex.class}] #{ex.message}"
    echo "Waiting 1.26 seconds for actor to be reinstantiated."
    sleep 1.26
  end
}

显著变化:

  1. 首先调用Celluloid,并让它正常旋转
  2. 不再在initialize中启动服务器
  3. 捕获服务器的死亡,并在重新实例化参与者后重新启动它
  4. 遵守新的API
  5. 最后强制、静默地关闭服务器
  6. 在断开连接时用力、无声地关闭插座
  7. 避免重复Celluloid本身已经启动的关闭
  8. 避免使用通常不存在的主机名。显示数字地址
  9. 捕捉由写入引起的错误类型,并向您显示原因
  10. 无论插座如何死亡,插座总是会闭合

您最初启动的代码应该是有效的,或者至少它应该给您一个不起作用的明确原因。从0.17.0开始,上述代码现在与Celluloid兼容,并且与新的Celluloid::IO兼容。。。如果您有任何进一步的问题,请包括具体的错误。

注意:您可能需要检测到服务器崩溃,并且仍然打开您期望可用的端口,而这不包括在示例中。。。但Celluloid::IO测试套件中给出了一个例子:

  • assign_port中:https://github.com/celluloid/celluloid-io/commit/dc352d5a4d86684ad7cc8bc3b348ee7e9d92f8b3#L47

最新更新