如何发送组播消息并在Erlang中重用一个端口? [英] How to send multicast messages and reuse a port in Erlang?

查看:187
本文介绍了如何发送组播消息并在Erlang中重用一个端口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序,我的第一个REAL Erlang程序我已经开始了一个很好的开始。
我听到消息,读取它们并解析它们。我也有它发送他们。
困扰我的一件小事是我不能在5353端口发送,我已经尝试了一切。
我机器上的所有其他应用程序可以侦听并发送端口5353,SubEthaEdit,iTunes,iChat。



解决方案必须广播发送端口5353,这就是为什么。



如果接收到的多播DNS查询中的源UDP端口不是端口
5353,表示发起查询的客户端是
简单客户端,不能完全实现所有的组播DNS
在这种情况下,组播DNS响应者必须直接发送一个UDP响应
客户端通过单播到查询数据包的
源IP地址和端口,这种单播响应必须是传统的单播DNS服务器生成的传统单播响应
;例如,它必须重复查询数据包中给出的查询ID和
问题



它们都报告端口:5353 when发送组播消息。
我真的希望我的应用程序玩得很好,做同样的事情,发送在端口5353.
这是我现在的模块。

   - 模(零配置)。 

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

发送(域) - >
{ok,S} = gen_udp:open(0,[{broadcast,true}]),%我真的希望这个端口是5353 :-(
%这不会抱怨或抛出错误但是它也不起作用:-(
%{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)

这是一些输出如何。



这是一个来自SubEthaEdit的QUERY,在本地查找其他实例网络,通知它说端口:5353

 从:{192,168,0,105} 
端口:5353
数据:{ok,{dns_rec,{dns_header,0,true,'query',true,false,false,false,false,0},
[],
[{dns_rr, ._tcp.local,ptr,in,0,0,
jhr @ Blackintos h._see._tcp.local,undefined,[],
false}],
[],[]}}

现在,我的模块查询QUERY,在本地网络上查找iTunes的实例,注意到端口:59795
以现在的代码为例,端口是随机的。我真的想要它是5353。

 从:{192,168,0,105} 
端口:59795
数据:{ok,{dns_rec,{dns_header,0,false,'query',false,false,false,false,false,
0},
[{dns_query,_ daap._tcp.local ,ptr,in}],
[],[],[]}}



解决方案

更新:好的,我找到了我相信是一个工作的解决方案。关键点似乎与加入多播组有关。

  {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守护程序)


I have gotten a good start on my program, my first REAL Erlang program. I have it listening for messages, reading them and parsing them. I also have it sending them. The one little thing that is bothering me is I can't SEND on Port 5353, I have tried everything. All the other applications on my machine can listen AND send on port 5353, SubEthaEdit, iTunes, iChat.

The solution MUST broadcast send on port 5353 and here is why.

" If the source UDP port in a received Multicast DNS Query is not port 5353, this indicates that the client originating the query is a simple client that does not fully implement all of Multicast DNS. In this case, the Multicast DNS Responder MUST send a UDP response directly back to the client, via unicast, to the query packet's source IP address and port. This unicast response MUST be a conventional unicast response as would be generated by a conventional unicast DNS server; for example, it MUST repeat the query ID and the question given in the query packet. "

They all report Port: 5353 when sending multicast messages. I really want my application to play nice and do the same thing, send on Port 5353. Here is my module as it stands now.

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

Here is what some output looks like.

This is a QUERY from SubEthaEdit looking for other instances on the local network, notice that it says 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,
                            "jhr@Blackintosh._see._tcp.local",undefined,[],
                            false}],
                   [],[]}}

Now here is a QUERY from my module looking for instances of iTunes on the local network, notice it says Port: 59795 With the code the way it is now, that port is random. I really want it to be 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}],
                   [],[],[]}}

Does anyone have any arcane insight in to UDP multicast at all? Updating so I can try and accept an answer. I think I just can't do this.

解决方案

UPDATED: ok, I have found what I believe to be a working solution. The crucial point it seems relate to joining a multicast group.

{ok, Socket} = gen_udp:open(Port=5353, [binary, {active, false}, {reuseaddr, true},
                                        {ip, Addr}, {add_membership, {Addr, IAddr}}]).

  1. Addr: multicast group (e.g. {224, 0, 0, 251}
  2. IAddr is a local IP interface (e.g. can use default {0,0,0,0})

( Of course, make sure that you are not running DNS daemon that might enter in conflict)

这篇关于如何发送组播消息并在Erlang中重用一个端口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆