2009-11-17 15 views
7

Ich habe einen guten Start in mein Programm bekommen, mein erstes REAL Erlang Programm. Ich höre auf Nachrichten, lese sie und analysiere sie. Ich habe es auch gesendet. Das eine kleine Ding, das mich stört ist, dass ich nicht auf Port 5353 SENDEN kann, ich habe alles versucht. Alle anderen Anwendungen auf meinem Rechner können hören und senden an Port 5353, SubEthaEdit, iTunes, iChat.Wie sende ich Multicast-Nachrichten und verwende einen Port in Erlang?

Die Lösung muss Broadcast senden an Port 5353 und hier ist warum.

"Wenn der UDP-Quellport in einer empfangenen Multicast-DNS-Abfrage nicht Port ist 5353, zeigt dies an, dass der Client die Abfrage Ursprung ist ein einfacher Client, der nicht vollständig alle Multicast DNS nicht implementiert. In diesem In diesem Fall MUSS der Multicast-DNS-Responder eine UDP-Antwort direkt an den Client über Unicast an die Quell-IP-Adresse und den Port des Abfragepakets senden Diese Unicast-Antwort MUSS eine herkömmliche Unicast-Antwort sein, wie sie von einem herkömmlichen generiert würde Unicast-DNS-Server, zum Beispiel, es muss die Abfrage-ID und die Frage im Abfragepaket gegeben wiederholen. "

Sie alle melden Port: 5353 beim Senden von Multicast-Nachrichten. Ich möchte wirklich, dass meine Anwendung nett spielt und dasselbe macht, sende Port 5353. Hier ist mein Modul, wie es jetzt steht.

-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). 

Hier ist, wie eine Ausgabe aussieht.

Dies ist ein QUERY von SubEthaEdit für andere Instanzen im lokalen Netzwerk suchen bemerken, dass es sagt Hafen: 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}], 
        [],[]}} 

Hier ein QUERY von meinem Modul ist im lokalen Netzwerk für Instanzen von iTunes suchen Beachten Sie, dass Port: 59795 Mit dem Code, wie es jetzt ist, ist dieser Port zufällig. Ich will es wirklich sein 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}], 
        [],[],[]}} 

Hat jemand irgendwelche obskuren Einblick in UDP-Multicast überhaupt? Aktualisieren, damit ich versuchen kann, eine Antwort zu akzeptieren. Ich denke, ich kann das einfach nicht tun.

Antwort

3

AKTUALISIERT: ok, ich habe gefunden, was ich glaube, eine funktionierende Lösung zu sein. Der entscheidende Punkt, den es scheint, bezieht sich auf Beitritt einer Multicast-Gruppe.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. Addr: Multicast-Gruppe (z.B. {224, 0, 0, 251}
  2. IADDR ist eine lokale IP-Schnittstelle (z.B.verwenden können default {0,0,0,0})

(Natürlich, stellen Sie sicher, dass Sie nicht DNS-Daemon ausführen, die in Konflikt geben könnte)

0

Sie versuchen, eine Steckdose zu öffnen, die bereits geöffnet ist? Können Sie nicht den gleichen Socket zum Senden von und Empfänger verwenden?

+0

Ich denke nicht, weil ich die {broadcast, true} Option zum Senden übergeben muss. –

+0

Ist es nicht möglich {broadcast, true/false} mit inet: setopts/2 zu ändern, wenn Sie eine Nachricht senden? – emil

+0

Ich kann es nicht bekommen, um eine Nachrichtenperiode mit irgendwelchen davon zu senden oder nicht. –

1

haben nicht genug rep antworten zu der {broadcast, true} Diskussion unter emils Post, sorry.

Das SO_BROADCAST-Socket-Flag (dem ich vermute, dass Maps auf) muss gesetzt oder sendto (eine Broadcast-Adresse) wird fehlschlagen. Dies ist eine Sicherheitsvorkehrung, um Missbrauch oder Fehler bei Programmen zu verhindern, die nicht gesendet werden wollten. Andernfalls müssten sichere Programme versuchen, selbst nach Broadcast-Adressen zu suchen.

Das Aktivieren von SO_BROADCAST hindert Sie nicht daran, Nicht-Broadcast-Pakete zu senden. (wieder, vorausgesetzt, Erlangs Sachen sind nur direkt auf Setsockopts abgebildet; ich weiß nicht, Erlang, nur Vernetzung!)

Sie möchten Strace versuchen, um zu sehen, was Systemaufrufe tatsächlich passieren. Suchen Sie nach socket() und was passiert dann mit diesem Dateideskriptor?