2009-11-17 18 views
7

Ho iniziato bene il mio programma, il mio primo vero programma Erlang. L'ho ascoltato per i messaggi, li ho letti e li ho analizzati. Ho anche l'invio di loro. L'unica piccola cosa che mi dà fastidio è che non posso INVIARE su Port 5353, ho provato di tutto. Tutte le altre applicazioni sulla mia macchina possono ascoltare e inviare sulla porta 5353, SubEthaEdit, iTunes, iChat.Come inviare messaggi multicast e riutilizzare una porta in Erlang?

La soluzione DEVE trasmettere trasmettere sulla porta 5353 ed ecco perché.

"Se la fonte porta UDP in una ricevuta Multicast DNS query non è la porta 5353, questo indica che il client di origine la query è un semplice client che non implementa pienamente tutti Multicast DNS. In questo caso, il risponditore DNS multicast DEVE inviare una risposta UDP direttamente al client, tramite unicast, all'indirizzo e alla porta IP di origine del pacchetto della query . Questa risposta unicast DEVE essere una risposta unicast convenzionale come sarebbe generata da un convenzionale server DNS unicast, ad esempio, DEVE ripetere l'ID query e la domanda indicata nel pacchetto di query. "

Tutti segnalano Porta: 5353 quando si inviano messaggi multicast. Voglio davvero che la mia applicazione funzioni correttamente e faccia la stessa cosa, invia su Port 5353. Ecco il mio modulo così com'è ora.

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

Ecco come appare un output.

Si tratta di una query da SubEthaEdit alla ricerca di altre istanze sulla rete locale, si noti che si dice Port: 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}], 
        [],[]}} 

Ora qui è una query dal mio modulo alla ricerca di istanze di iTunes sulla rete locale , si noti che porta: 59795 Con il codice così com'è ora, quella porta è casuale. Voglio davvero che sia 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}], 
        [],[],[]}} 

Qualcuno ha alcuna conoscenza arcana per UDP multicast a tutti? Aggiornamento così posso provare ad accettare una risposta. Penso di non poterlo fare.

risposta

3

AGGIORNATO: ok, ho trovato quello che credo sia una soluzione funzionante. Il punto cruciale sembra riguardare lo che si aggiunge a un gruppo multicast.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. Addr: gruppo multicast (ad esempio {224, 0, 0, 251}
  2. IAddr è un'interfaccia IP locale (ad esempiopuò usare predefinita {0,0,0,0})

(Naturalmente, assicurarsi che non sia in esecuzione daemon DNS che potrebbe entrare in conflitto)

0

Si tenta di aprire un socket che è già aperto? Non è possibile utilizzare lo stesso socket per l'invio di e?

+0

Non penso perché ho bisogno di passare l'opzione {broadcast, true} per l'invio. –

+0

Non è possibile modificare {broadcast, vero/falso} con inet: setopts/2 quando si invia un messaggio, quindi? – emil

+0

Non riesco a far sì che invii un periodo di messaggio con uno qualsiasi di questo set o no. –

1

non hanno abbastanza rep di rispondere alla discussione {broadcast, true} sotto il post di emil, mi dispiace.

Il flag di socket SO_BROADCAST (che presumo che le mappe siano) deve essere impostato o sendto (un indirizzo di broadcast) non riuscirà. Questa è una presa di sicurezza per prevenire abusi o errori con programmi che non intendevano trasmettere. In caso contrario, i programmi sicuri dovrebbero cercare di verificare autonomamente gli indirizzi di trasmissione.

abilitando SO_BROADCAST non impedisce l'invio di pacchetti non broadcast. (di nuovo, supponendo che le cose di erlang siano solo mappe direttamente su setsockopts; non conosco l'erlang, solo networking!)

Si potrebbe voler provare strace per vedere quali chiamate di sistema effettivamente accadono. cercare socket(), quindi cosa succede a quel descrittore di file.

Problemi correlati