0

I'm writing a ruby program that has 2 threads. One that listens on an incoming UDP connection and another that broadcasts on a websocket from which browsers on the client side read.I'm using the em-websocket gem. However, My UDP listener thread never gets called and it looks like the code stays within the websocket initialization code. I'm guessing because em-websocket is blocking, but I haven't been able to find any info online that suggests that. Is it an error on my side? I'm kinda new to ruby so I'm not able to figure out what I'm doing wrong.

require 'json'
require 'em-websocket'
require 'socket'

socket=nil
text="default"
$x=0

EventMachine.run do
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
  ws.onopen    { 
            ws.send "Hello Client!"
            socket=ws
            $x=1
        }

  ws.onmessage { |msg| socket.send "Pong: #{msg}" }
  ws.onclose   { puts "WebSocket closed" }
end
end
def listen()
puts "listening..."
s = UDPSocket.new
s.bind(nil, 3000)
while 1<2 do
  text, sender = s.recvfrom(1024)     
  puts text
  if $x==1 then
    socket.send text      
  end   
end
end

t2=Thread.new{listen()}
t2.join
4

1 回答 1

4

em-websocket是非阻塞的,但是UDPSocket#recv_from是。改用 EventMachine 可能会更好open_datagram_socket

另一件需要注意的事情:您不应该公开socket为“全局”变量。每次有人连接到先前连接的客户端的引用都会丢失。也许为套接字连接创建某种存储库,或者使用观察者模式在有东西进入时广播消息。我要做的是让一个虚拟对象充当观察者,并且每当连接/断开套接字时,您就注册/取消注册观察者:

require 'observer'

class Dummy
  include Observable

  def receive_data data
    changed true
    notify_observers data
  end
end

# ... later on ...

$broadcaster = Dummy.new

class UDPHandler < EventMachine::Connection
  def receive_data data
    $broadcaster.receive_data data
  end
end

EventMachine.run do
  EM.open_datagram_socket "0.0.0.0", 3000, UDPHandler

  EM::WebSocket.start :host => "0.0.0.0", :port => 8080 do |ws|
    ws.onopen do
      $broadcaster.add_observer ws
    end

    ws.onclose do
      $broadcaster.delete_observer ws
    end

    # ...
  end
end

EventMachine 的全部意义在于抽象出基本的套接字和线程结构,并在内部处理所有异步位。最好不要将经典库UDPSocketThreadEventMachine 之类的东西混合使用。

于 2012-06-12T01:30:13.287 回答