2009-11-17 9 views
7

私は最初のREAL Erlangプログラムで私のプログラムをうまくスタートしました。 私はメッセージを聞いて、それを読み、パースしました。私もそれを送ってきました。 私に迷惑をかける小さなことは、ポート5353で送信できないことです。私はすべてを試しました。 私のマシン上の他のすべてのアプリケーションは、ポート5353、SubEthaEdit、iTunes、iChatを聴いて送信することができます。Erlangでマルチキャストメッセージを送信してポートを再利用する方法は?

ソリューションは、ポート5353でブロードキャストしなければならず、理由はここにあります。

「受信マルチキャストDNSクエリが 5353ポートではありません元UDPポートで、このクエリを元のクライアントが完全にマルチキャストDNSのすべてを実装していない シンプルなクライアントであることを示している場合。この中 マルチキャストDNSレスポンダはユニキャストを介してUDPパケットの をユニキャストで直接送信しなければならない(MUST)。 送信元IPアドレスとポート。例えばユニキャストDNSサーバでなければなりません;例えば、それは質問IDと質問パケットで与えられた 質問を繰り返さなければなりません。 "

マルチキャストメッセージを送信すると、すべてポート:5353が報告されます。 ポート5353を送信して、私のアプリケーションがうまくやり直して同じことをしたいのです。 ここに私のモジュールがあります。

-module(zeroconf). 

-include("zeroconf.hrl"). 

-export([open/0,start/0]). 
-export([stop/1,receiver/0]). 
-export([send/1]). 

-define(ADDR, {224,0,0,251}). 
-define(PORT, 5353). 

send(Domain) -> 
    {ok,S} = gen_udp:open(0,[{broadcast,true}]), % I really want this Port to be 5353 :-(
    % this doesn't complain or throw errors but it also doesn't work :-(  
    %{ok,S} = gen_udp:open(?PORT,[{reuseaddr,true}, {ip,?ADDR}, {broadcast,true},multicast_ttl,4}, {multicast_loop,false}, binary]), 
    P = #dns_rec{header=#dns_header{},qdlist=[#dns_query{domain=Domain,type=ptr,class=in}]}, 
    gen_udp:send(S,?ADDR,?PORT,inet_dns:encode(P)), 
    gen_udp:close(S). 

出力は次のようになります。今ここに5353

From: {192,168,0,105} 
Port: 5353 
Data: {ok,{dns_rec,{dns_header,0,true,'query',true,false,false,false,false,0}, 
        [], 
        [{dns_rr,"_see._tcp.local",ptr,in,0,0, 
          "[email protected]_see._tcp.local",undefined,[], 
          false}], 
        [],[]}} 

私のモジュールからのQUERYは、ローカルネットワーク上のiTunesのインスタンスを探している:

これは、ローカルネットワーク上の他のインスタンスを探してSubEthaEditからQUERY、ですが、それは、ポートが言うことに気付きます、それが言うポートに気づく:59795 今のところコードと、そのポートはランダムです。私は本当にそれが5353であることを望みます。

From: {192,168,0,105} 
Port: 59795 
Data: {ok,{dns_rec,{dns_header,0,false,'query',false,false,false,false,false, 
           0}, 
        [{dns_query,"_daap._tcp.local",ptr,in}], 
        [],[],[]}} 

誰もがUDPマルチキャストに秘密の洞察力を持っていますか?更新するので、私は答えを受け入れることができます。私はちょうどこれをすることができないと思う。

答えて

3

更新済み:私は実用的なソリューションであると確信しています。それは、マルチキャストグループに参加することに関連しているように見える重要な点

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. ADDR:マルチキャストグループ(例えば{224、0、0、251}
  2. IADDRローカルIPインターフェース(例えばデフォルト{0,0,0,0})

(もちろん、あなたが競合に入る可能性があるDNSデーモンを実行していないことを確認してください)

0

すでに開いているソケットを開こうとしていますか? を送信するために同じソケットを使用できませんか?

+0

送信するために{broadcast、true}オプションを渡す必要があるので、私はそうは思わない。 –

+0

メッセージを送信するときに、inet:setopts/2で{broadcast、true/false}を変更することはできませんか? – emil

+0

私はそれが設定されているかどうかにかかわらずメッセージ期間を送ることができません。 –

1

が返信するのに十分な担当者を持っていない使用することができますemilの投稿の下にある{broadcast、true}の議論に、申し訳ありません。

SO_BROADCASTソケットフラグ(マップすると仮定します)を設定するか、sendto(ブロードキャストアドレス)を失敗させる必要があります。これは、放送するつもりのないプログラムの悪用やエラーを防ぐための安全キャッチです。さもなければ、安全なプログラムはブロードキャストアドレス自体をチェックしようとするでしょう。

SO_BROADCASTを有効にしても、ブロードキャスト以外のパケットを送信することはできません。 (エルランのものはsetsockoptsに直接マップされていると仮定して、私はエルランを知りません、ネットワーキングだけです)

実際にどのようなシステムコールが起こるかを見るには、straceを試してみてください。 socket()を探し、そのファイル記述子に何が起こるかを調べます。

関連する問題