2009-11-17 7 views
7

J'ai pris un bon départ pour mon programme, mon premier programme REAL Erlang. Je l'ai écouté pour les messages, les lire et les analyser. Je l'ai aussi en train de les envoyer. La seule petite chose qui me dérange est que je ne peux pas envoyer sur le port 5353, j'ai tout essayé. Toutes les autres applications sur ma machine peuvent écouter ET envoyer sur le port 5353, SubEthaEdit, iTunes, iChat.Comment envoyer des messages multicast et réutiliser un port dans Erlang?

La solution DOIT diffuser l'envoi sur le port 5353 et voici pourquoi.

"Si le port source UDP dans un reçu Multicast requête DNS est pas le port 5353, cela signifie que le client d'origine de la requête est un client simple qui ne met pas en œuvre pleinement tous Multicast DNS. Dans ce Dans le cas contraire, le répondeur DNS Multicast DOIT envoyer une réponse UDP directement au client, via unicast, à l'adresse IP source et au port du paquet de requête Cette réponse DOIT être une réponse d'unicast comme serait générée par un classique serveur DNS unicast, par exemple, il DOIT répéter l'ID de requête et la question donnée dans le paquet de requête. "

Ils signalent tous le port: 5353 lors de l'envoi de messages multidiffusés. Je veux vraiment que mon application joue bien et fasse la même chose, envoie sur le port 5353. Voici mon module tel qu'il est maintenant.

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

Voici à quoi ressemble une sortie.

Ceci est une question de SubEthaEdit la recherche d'autres cas sur le réseau local, notez qu'il est dit 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}], 
        [],[]}} 

Maintenant, voici un QUERY de mon module recherche d'instances d'iTunes sur le réseau local , notez-le dit Port: 59795 Avec le code tel qu'il est maintenant, ce port est aléatoire. Je veux vraiment que ce soit 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}], 
        [],[],[]}} 

Quelqu'un at-il une idée Arcane pour UDP multicast du tout? Mise à jour pour que je puisse essayer et accepter une réponse. Je pense que je ne peux pas faire ça.

Répondre

3

MISE À JOUR: ok, j'ai trouvé ce que je crois être une solution de travail. Le point crucial, il semble se rapporter à joindre un groupe de multidiffusion.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. Adr: groupe de multidiffusion (par exemple {224, 0, 0, 251}
  2. IADDR est une interface IP locale (par exemple,peut utiliser par défaut {0,0,0,0})

(Bien sûr, assurez-vous que vous n'êtes pas en cours d'exécution démon DNS qui pourrait entrer en conflit)

0

Vous essayez d'ouvrir une socket qui est déjà ouverte? Vous ne pouvez pas utiliser le même socket pour envoyer et recevoir?

+0

Je ne pense pas parce que je dois passer l'option {broadcast, true} pour l'envoi. –

+0

Il n'est pas possible de changer {broadcast, true/false} avec inet: setopts/2 quand vous envoyez un message alors? – emil

+0

Je ne peux pas l'obtenir pour envoyer une période de message avec un de ces ensembles ou non. –

1

n'ont pas assez représentant de répondre à la {broadcast, true} discussion sous la poste d'emil, désolé.

L'indicateur de socket SO_BROADCAST (que je suppose que mappage vers) doit être défini ou sendto (une adresse de diffusion) échouera. C'est une sécurité pour éviter les abus ou les erreurs avec des programmes qui n'ont pas l'intention de diffuser. Sinon, les programmes sécurisés devraient essayer de vérifier eux-mêmes les adresses de diffusion.

L'activation de SO_BROADCAST ne vous empêche pas d'envoyer des paquets non diffusés. (encore une fois, en supposant que les trucs d'erlang sont mappés directement à setsockopts, je ne sais pas erlang, juste en réseau!)

Vous pouvez essayer de voir quels appels système se produisent réellement. Recherchez socket(), puis qu'arrive-t-il à ce descripteur de fichier.

Questions connexes