2009-11-17 6 views
7

제 첫 번째 실제 Erlang 프로그램에서 좋은 시작을 얻었습니다. 메시지를 듣고 읽고 파싱합니다. 나는 또한 그것을 보내고있다. 나를 귀찮게하는 작은 한가지는 포트 5353에서 보낼 수 없다는 것입니다. 나는 모든 것을 시도했습니다. 내 컴퓨터의 다른 모든 응용 프로그램은 포트 5353, SubEthaEdit, iTunes, iChat을 수신하고 보낼 수 있습니다.Erlang에서 멀티 캐스트 메시지를 보내고 포트를 재사용하는 방법은 무엇입니까?

솔루션은 포트 5353에서 브로드 캐스트를 보내야하며 여기에 그 이유가 나와 있습니다. 수신 된 멀티 캐스트 DNS 쿼리의 소스 UDP 포트가 5353 포트가 아닌 경우

는 "이 쿼리를 발생하는 클라이언트가 완전히이 멀티 캐스트 DNS의 모든. 를 구현하지 않는 간단한 클라이언트가 있음을 나타냅니다 멀티 캐스트 DNS 응답자는 쿼리 패킷의 원본 IP 주소 및 포트로 유니 캐스트를 통해 클라이언트에 직접UDP 응답을 보내야합니다.이 유니 캐스트 응답은 으로 생성되는 일반적인 유니 캐스트 응답 인 이어야합니다. 유니 캐스트 DNS 서버, 예를 들어 쿼리 패킷에 주어진 쿼리 ID와 질문을 반복해야합니다. "

멀티 캐스트 메시지를 보낼 때 모두 포트 : 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). 

일부 출력은 다음과 같습니다. 이제 여기에 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}], 
        [],[]}} 

내 모듈에서 쿼리가 로컬 네트워크에서 iTunes의 인스턴스를 찾고 있습니다 :

이 로컬 네트워크에있는 다른 인스턴스를 찾고 SubEthaEdit에서 QUERY이다는 포트 말하는 것을 알 수 그것이 포트라고 말한 것을 주목하십시오 : 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 멀티 캐스트에 대해 어떤 비밀스런 통찰력을 가지고 있지 않습니까? 업데이트 중이므로 답변을 수락 할 수 있습니다. 나는 단지 이것을 할 수 없다고 생각한다.

답변

3

업데이트 됨 : 알았습니다. 나는 실제 해결책이라고 생각합니다. 그것이 멀티 캐스트 그룹에 합류하는 과 관련된 것처럼 보이는 중요한 점.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true}, 
             {ip, Addr}, {add_membership, {Addr, IAddr}}]). 
  1. 번지 기능은 : 멀티 캐스트 그룹 (예를 들면 {224, 0, 0, 251}
  2. IAddr 로컬 IP 인터페이스 (예를 들어당신이 충돌 입력 할 수 있습니다 DNS 데몬)를 실행되지 않도록, 물론 기본 {0,0,0,0})

을 (사용할 수 있습니다

0

당신은 이미 열려있는 소켓을 열려고? 을 수신 할 때 동일한 소켓을 사용할 수 없습니까?

+0

전송하기 위해 {broadcast, true} 옵션을 전달해야하므로 그렇게 생각하지 않습니다. –

+0

메시지를 보낼 때 inet : setopts/2로 {broadcast, true/false}를 변경할 수 없습니까? – emil

+0

메시지주기를 보내거나 가져올 수 없습니다. –

1

충분히 담당자 답장이없는 에밀의 게시물 아래 {브로드 캐스트, 트루} 토론으로

SO_BROADCAST 소켓 플래그 (맵핑한다고 가정)를 설정해야하거나 sendto (브로드 캐스트 주소)가 실패합니다. 이것은 방송용이 아닌 프로그램의 남용이나 오류를 막기위한 안전 장치입니다. 그렇지 않으면 보안 프로그램 자체가 브로드 캐스트 주소를 확인해야합니다.

SO_BROADCAST를 사용하면 비 브로드 캐스트 패킷을 보내지 않습니다. (다시, erlang의 것들이 setsockopts에 직접 매핑된다고 가정하면, 나는 네트워크를 알지 못한다.)

어떤 시스템 호출이 실제로 일어나는지 보려면 strace를 시도해 볼 수있다. socket()을 찾은 다음 그 파일 디스크립터에 어떤 일이 일어나는지.