-1

我正在使用 em-websocket gem 制作一个 Ruby 服务器。当客户端发送一些消息(例如“线程”)时,服务器会创建两个不同的线程并将两个 anwsers 并行发送到客户端(我实际上正在研究多线程和 websockets)。这是我的代码:

EM.run {
  EM::WebSocket.run(:host => "0.0.0.0", :port => 8080) do |ws|
    ws.onmessage { |msg|
      puts "Recieved message: #{msg}"
      if msg == "thread"
        threads = []
        threads << a = Thread.new {
          sleep(1)
          puts "1"
          ws.send("Message sent from thread 1")
        }
        threads << b = Thread.new{
          sleep(2)
          puts "2"
          ws.send("Message sent from thread 2")
        }
        threads.each { |aThread| aThread.join }
      end

它是如何执行的:

  • 我正在向服务器发送“线程”消息
  • 在我的控制台中一秒钟后,我看到打印的字符串“1”。又过了一秒钟,我看到“2”。
  • 只有在那之后,两条消息才会同时发送到客户端。

问题是我想在发送调试输出“1”和“2”的同时发送消息。

我的 Ruby 版本是 1.9.3p194。

4

2 回答 2

0

我认为问题在于您正在调用 sleep 方法,将 1 传递给第一个线程,将 2 传递给第二个线程。尝试删除两个线程上的睡眠调用或在每次调用中传递相同的值。

于 2013-07-04T13:39:29.193 回答
0

我没有使用 EM 的经验,所以请加一点盐。

但是,乍一看,“aThread.join”似乎实际上阻止了“onmessage”方法的完成,从而也阻止了“ws.send”的处理。您是否尝试过删除“threads.each”块?

编辑:在使用 ruby​​ 1.9.3 和 2.0.0(使用 em-websocket 示例中的“test.html”)在 arch linux 中对此进行测试后,我确信即使删除“threads.each”块也不会'不要为您解决问题,您仍然必须将其删除,因为Thread#join将暂停当前线程,直到“加入”线程完成。

如果通过源码跟踪“ws.onmessage”的函数调用,最终会 看到Eventmachine模块的Connection#send_data方法,并在注释中找到以下内容:

调用此方法将数据发送到网络连接的远程端。它需要一个字符串参数,其中可能包含二进制数据。数据被缓冲以在此事件循环滴答(循环)结束时发送。

由于“onmessage”被“join”阻塞,直到两个“send”方法都运行,事件循环滴答才能完成,直到两个数据集都被缓冲,因此,直到这个时候才能发送所有数据。

如果删除“threads.each”块后它仍然不适合您,请确保您已重新启动事件机器并尝试将第二次睡眠设置为 5 秒。我不知道一个典型的事件循环在 eventmachine 中需要多长时间(我无法想象它会长达一秒钟),但是,文档基本上说如果在同一个滴答声中进行了多个“发送”调用, 它们都将同时发送。因此,增加时差将确保不会发生这种情况。

于 2013-07-04T14:05:02.883 回答