0

私は2つのスレッドを持つrubyプログラムを書いています。1つは着信UDP接続をリッスンし、もう1つはクライアント側のブラウザーが読み取るWebSocketでブロードキャストします。私はem-websocketgemを使用しています。ただし、UDPリスナースレッドが呼び出されることはなく、コードはWebSocket初期化コード内にとどまっているようです。em-websocketがブロックしているためだと思いますが、それを示唆する情報をオンラインで見つけることができませんでした。それは私の側のエラーですか?私はルビーに少し慣れていないので、自分が間違っていることを理解することができません。

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

注意すべきもう1つのこと: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の要点は、基本的なソケットとスレッド構造から抽象化し、すべての非同期ビットを内部で処理することです。UDPSocketEventMachineのもののような、またはThreadEventMachineのものと古典的なライブラリを混合しないことが最善です。

于 2012-06-12T01:30:13.287 に答える