2009-11-17 15 views
7

Programıma, ilk REAL Erlang programına iyi bir başlangıç ​​yaptım. Mesajları dinliyorum, okuyor ve ayrıştırıyorum. Onları da gönderiyorum. Beni rahatsız eden küçük bir şey, 5353 numaralı bağlantı noktasında gönderemem, her şeyi denedim. Makinemdeki diğer tüm uygulamalar, 5353, SubEthaEdit, iTunes, iChat bağlantı noktasını dinleyebilir ve gönderebilir.Çok noktaya yayın iletileri nasıl gönderilir ve Erlang'da bir bağlantı noktası yeniden kullanılır?

Çözüm 5353 numaralı bağlantı noktasında gönderilmeli ZORUNLUdur ve işte bu yüzden. Alınan Multicast DNS Sorgusu kaynak UDP bağlantı noktası 5353 portu değilse

", bu sorguyu menşeli istemci tam bu ise Çoklu Yayın DNS hepsini. uygulamayan bir basit istemci olduğunu gösterir dava, Multicast DNS Yanıtlayıcı sorgu paketin kaynak IP adresi ve port için, tek noktaya yoluyla doğrudan geri istemciye UDP yanıtı göndermek zorundadır. Bu tek noktaya tepki geleneksel yaratacağı gibi geleneksel tek noktaya tepki OLMALIDIR tek noktaya yayın DNS sunucusu, örneğin sorgu kimliğinde ve sorgu paketinde verilen sorusunu tekrarlamalıdır. "

Hepsi çok noktaya yayın iletileri gönderirken Port: 5353 bildiriyor. Uygulamamın gerçekten güzel oynamasını ve aynı şeyi yapmasını istiyorum, 5353 numaralı bağlantı noktasında gönderin. İşte benim modülüm şu anki haliyle.

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

Bazı çıktılar şöyle görünüyor. Şimdi burada 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}], 
        [],[]}} 

benim modülünden bir SORGU yerel ağdaki iTunes örnekleri arayan geçerli:

Bu, yerel ağdaki diğer durumlarda arayan SubEthaEdit bir SORGU olduğunu o Liman diyor fark , dikkat edin diyor Port: 59795 Kod şimdi olduğu gibi, bu port rastgele. Gerçekten olmasını istiyorum 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}], 
        [],[],[]}} 

kimse hiç UDP multicast için herhangi gizli bir fikir var mı? Güncellemek için bir cevap kabul edip kabul edebilirim. Sanırım bunu yapamam.

cevap

3

GÜNCELLEME: Tamam, çalışma çözümü olduğuna inandığım şeyi buldum. Göründüğü en önemli nokta, çok noktaya yayın grubunu birleştiren ile ilgilidir.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. Adresi: çok noktaya yayın grubu (örneğin, {224, 0, 0, 251}
  2. IAddr yerel bir IP arabirimidir (örEğer çatışma girebilirsiniz DNS cini) çalışmadığından emin olun Tabii varsayılan {0,0,0,0})

(kullanabilirsiniz

0

Zaten açık olan bir soketi açmaya çalışıyorsunuz? ve numaralarını göndermek için aynı soketi kullanamaz mısınız?

+0

Bunu düşünmüyorum çünkü gönderme için {broadcast, true} seçeneğini kullanmam gerekiyor. –

+0

Mesaj gönderirken {broadcast, true/false} ile inet: setopts/2 değiştirmek mümkün değil mi? – emil

+0

Bu setten herhangi biriyle bir mesaj süresi göndermek için alamıyorum. –

1

yeterli temsilcisi cevap gelmiş değil emil yayınının altındaki {broadcast, true} tartışmaya, özür dilerim.

ayarlanmalıdır veya sento (bir yayın adresi) başarısız olacaktır (Ben haritalar için varsayalım) SO_BROADCAST soket bayrağı. Bu, yayınlamayı planlamayan programlarla kötüye kullanımı veya hataları önlemek için bir güvenlik önlemidir. Aksi halde güvenli programlar, yayın adreslerini kendileri kontrol etmeye çalışmalıdır.

olmayan yayın paketlerini göndermenizi durmuyor SO_BROADCAST sağlayan. (tekrar, erlang'ın eşyalarının sadece setsockopts'a eşleştiğini varsayıyorum; erlang'i bilmiyorum, sadece ağ yapıyorum!)

Sistem çağrılarının gerçekte ne olduğunu görmek için strace'i denemek isteyebilirsiniz. socket() 'ı arayın ve sonra bu dosya tanıtıcısına ne olur.