2009-11-17 2 views
7

Я получил хорошее начало в своей программе, моей первой программе REAL Erlang. Я слушаю сообщения, читаю их и разбираю. Я также отправляю их. Одна мелочь, которая меня беспокоит, я не могу ОТПРАВИТЬ на Порт 5353, я все пробовал. Все остальные приложения на моей машине могут прослушивать и отправлять на порт 5353, SubEthaEdit, iTunes, iChat.Как отправить многоадресные сообщения и повторно использовать порт в Erlang?

Решение ДОЛЖНО транслировать посылку на порт 5353 и вот почему.

"Если источник UDP-порт в принятом Multicast DNS Query не порт 5353, это указывает на то, что клиент происходящий запрос является простой клиент, который не в полной мере реализовать все Multicast DNS. В этом случае, ответчик многоадресной DNS ДОЛЖЕН отправить ответ UDP непосредственно обратно клиенту через одноадресную передачу на адрес IP-адреса и порт исходного запроса пакета . Этот ответ на одноадресную рассылку ДОЛЖЕН быть обычным одноадресным ответом , который будет генерироваться обычным одноадресный DNS-сервер, например, он ДОЛЖЕН повторить идентификатор запроса и вопрос , заданный в пакете запроса. "

Все они сообщают о порте: 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). 

Вот как выглядит какой-то результат.

Это QUERY из SubEthaEdit ищет других случаях в локальной сети, обратите внимание, что он говорит, Порт: 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 в локальной сети , замечает, что говорит: Порт: 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 Multicast на всех? Обновление, чтобы я мог попробовать и принять ответ. Думаю, я просто не могу этого сделать.

ответ

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

Невозможно изменить {broadcast, true/false} с помощью inet: setopts/2, когда вы отправляете сообщение? – emil

+0

Я не могу заставить его отправить период сообщения с любым из этого набора или нет. –

1

не имеют достаточного количества респ чтобы ответить к {трансляции, истинной} дискуссии по почте Эмиля, извините.

Должен быть установлен флаг сокета SO_BROADCAST (который я предполагаю, что карты) должен быть установлен или sendto (широковещательный адрес) завершится с ошибкой. Это предупреждение о безопасности для предотвращения злоупотреблений или ошибок в программах, которые не предназначены для трансляции. В противном случае защищенные программы должны были бы попытаться проверить сами широковещательные адреса.

включение SO_BROADCAST не мешает вам отправлять нерансетированные пакеты. (опять же, полагая, что материал erlang просто сопоставляется непосредственно с setsockopts, я не знаю erlang, просто работаю в сети!)

Возможно, вы захотите попробовать strace, чтобы увидеть, что происходит на самом деле. найдите socket(), а затем что произойдет с этим файловым дескриптором.

Смежные вопросы