2011-10-24 10 views
0

を使用します。つまり、コードスニペットが機能します。二open_datagram_socketがコメント解除されている場合は、このエラーで失敗します:私は<a href="http://rubyeventmachine.com/" rel="nofollow">EventMachine</a>とUDPの接続に設定されたソケットオプション(特にSO_REUSEADDR)をしようとしています(UDP経由)EventMachineでSO_REUSEADDR

eventmachine.rb:844: `open_udp_socket '内:なしグラムソケット(例外RuntimeError)

をソースを見てから、それはそれのように見えます失敗した場合はnullを返しますが、それは驚くべきことではありません。ソケットオプションが正しく設定されていないようですが、何か間違っているかどうかを知るためにライブラリやRubyやソケットプログラミングに精通していません。私はこのライブラリがちょうどこのようなものをサポートしていないとは想像できませんが、私は推測することができます。

どのように私はSO_REUSEADDRは、データグラムソケットで動作するように入手できますか?

require 'eventmachine' 

class PassThruServer < EM::Connection 
    def initialize 
     set_sock_opt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true 
    end 
    def post_init() 
     # too late? 
#  set_sock_opt Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true 
    end 
    def receive_data(data) 
     puts "PT: "+ data.to_s() 
     send_datagram data, "localhost", 6060 
    end 
end 

class MessagePrinter < EM::Connection 
    def receive_data(data) 
     puts "MP: "+ data.to_s() 
    end 
end 

EM.run do 
    # pass through 
    EM.open_datagram_socket "localhost", 5050, PassThruServer 
# EM.open_datagram_socket "localhost", 5050, PassThruServer 

    # test consumer 
    EM.open_datagram_socket "localhost", 6060, MessagePrinter 

    # test producer 
    EM.open_datagram_socket "localhost", nil do |conn| 
     i = 1 
     EM.add_periodic_timer(3) do 
      data = "message: "+ i.to_s() +"\n" 
      conn.send_datagram data, "localhost", 5050 
      i += 1 
     end 
    end 
end 

TCPは常にSO_REUSEADDRを使用するようです。私は、UDPがソケットオプションをどこで初期化するのかわかりません。私が理解している限り、ソケットが実際に開かれる前にそれらを設定する必要がありますか?

私は本当に私はしかし、正しい場所に探していますことを確認するために、RubyのCバインディングを完全に理解していません。

答えて

1

私は、以下のパッチで作成したソケットを取得することができました。しかし、私はソケットのそれぞれにデータのコピーを受け取ることができませんでした。

*** em.cpp Tue Oct 25 10:52:22 2011 
--- em_.cpp Tue Oct 25 10:51:38 2011 
*************** EventMachine_t::OpenDatagramSocket 
*** 1572,1577 **** 
--- 1572,1578 ---- 
    const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int port) 
    { 
      unsigned long output_binding = 0; 
+   int one = 1; 

      int sd = socket (AF_INET, SOCK_DGRAM, 0); 
      if (sd == INVALID_SOCKET) 
*************** const unsigned long EventMachine_t::Open 
*** 1606,1611 **** 
--- 1607,1615 ---- 
          goto fail; 
      } 

+   if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one)) < 0) 
+     goto fail; 
+ 
      if (bind (sd, (struct sockaddr*)&sin, sizeof(sin)) != 0) 
        goto fail; 

私の使用例は、図書館の著者によって全く考慮されていないと思います。設定が必要な他のソケットオプションはIP_ADD_MEMBERSHIPです。それは、私が推測しているC層に簡単にハックすることができます。私はそれをルビーレイヤーに公開しようとして失われます。私はそれが私の実践的な範囲を超えていると思う。

私はバニラルビーライブラリを使用することがより適切であると思います。

関連する問題