Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  Multicast

mlogan at futuresource.co
Posted: Thu Sep 02, 2004 7:04 pm Reply with quote
Guest
Is it possible to have multiple nodes on a single machine listening for
the same multicast packets at the same time? How can this be
accomplished within erts?

Cheers,
Martin



Post generated using Mail2Forum (http://m2f.sourceforge.net)
kramer at acm.org
Posted: Thu Sep 02, 2004 7:39 pm Reply with quote
Guest
The following works on the OSX and Linux for me. I had trouble opening
the multicast socket on WinXP, but no patience to figure out the cause.

cheers,
- Reto

Open a multicast port with:
Res = gen_udp:open(get_port(), [binary,
{reuseaddr,true},
{ip,get_addr()},
{multicast_loop,true},
{add_membership,{get_addr(),
{0,0,0,0}}}]),

where
get_addr() ->
{ok, App} = application:get_application(),
case application:get_env(App, addr) of
{ok, Val} ->
Val;
undefined ->
?ADDR
end.
get_port() -> ...

and the env key of the .app file is
{env, [{addr, {239,0,0,1}}, % the multicast ip addr
{port, 10042}, % the port we multicast at
{period, 1000}]}, % heartbeat interval in ms

Send packets with
Packet = {node_name, node()},
ok = gen_udp:send(State#state.socket,
get_addr(),
get_port(),
term_to_binary(Packet)),

and receive packets like this:
receive
{udp, Socket, IP, InPortNo, Packet} ->
{node_name, Node} = binary_to_term(Packet),

#

On Sep 2, 2004, at 12:03 PM, Martin J. Logan wrote:

> Is it possible to have multiple nodes on a single machine listening for
> the same multicast packets at the same time? How can this be
> accomplished within erts?
>
> Cheers,
> Martin
>



Post generated using Mail2Forum (http://m2f.sourceforge.net)
kramer at acm.org
Posted: Fri Sep 03, 2004 1:59 am Reply with quote
Guest
[ups, sent this from wrong account initially]

Martin,

Here's a complete testcase that you can run locally. It's a dumbed down
version of a larget app.

Compile this file and then run it in two terminals with:

erl -sname foo -s discover_server run
erl -sname bar -s discover_server run

Each node (foo and bar) will send numbered heartbeats to the multicast
address and each one will pick up it's own packets as well as packets
send by the other node.

(foo_at_yoghurt)1> Running for 5 minutes.
received packet 1 from node foo_at_yoghurt
received packet 2 from node foo_at_yoghurt
received packet 1 from node bar_at_yoghurt
received packet 3 from node foo_at_yoghurt
received packet 2 from node bar_at_yoghurt
received packet 4 from node foo_at_yoghurt
received packet 3 from node bar_at_yoghurt
received packet 5 from node foo_at_yoghurt

(bar_at_yoghurt)1> Running for 5 minutes.
received packet 2 from node foo_at_yoghurt
received packet 1 from node bar_at_yoghurt
received packet 3 from node foo_at_yoghurt
received packet 2 from node bar_at_yoghurt
received packet 4 from node foo_at_yoghurt
received packet 3 from node bar_at_yoghurt

This is running on one OSX box. E.g. foo picks up it's own heartbeat
2, and bar picks up that same packet (foo's heartbeat 2) as well. So
here they are not eating each others packets, but each process sees the
same packets.

Run it to see what you'll get on your setup.

cheers,
- Reto

%%%-------------------------------------------------------------------
%%% File : discover_server.erl
%%% Author : reto <kramer_at_acm.org>
%%% Description : Basic multicast based heart-beating
%%%-------------------------------------------------------------------
-module(discover_server).

-behaviour(gen_server).
%%--------------------------------------------------------------------
%% Include files
%%--------------------------------------------------------------------

%%--------------------------------------------------------------------
%% External exports
-export([start_link/0]).

-export([run/0]).

-export([trigger_heartbeat/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-record(state, {socket, % multicast udp socket
nodes, % set of nodes (atoms)
send_timer, % timer used to send heartbeats
counter
}).

-define(HB_PERIOD_MS, 1000). % (if not in .app) default hb interval
-define(ADDR, {239,0,42,1}). % (if not in .app) default addr
-define(PORT, 10042). % (if not in .app) default port

-define(SERVER, ?MODULE).

%%====================================================================
%% External functions
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link/0
%% Description: Starts the server
%%--------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%%====================================================================
%% Server functions
%%====================================================================

%%--------------------------------------------------------------------
%% Function: init/1
%% Description: Initiates the server
%% Returns: {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%%--------------------------------------------------------------------
init([]) ->
process_flag(trap_exit, true),
{ok, Socket} = gen_udp:open(get_port(), [binary,
{reuseaddr,true},
{ip,get_addr()},
{multicast_loop,true},
{add_membership,{get_addr(),
{0,0,0,0}}}]),
% net_kernel:monitor_nodes(true),
{ok, TRef} = timer:apply_interval(get_period(),
?MODULE, trigger_heartbeat, []),
{ok, #state{socket=Socket,
nodes=sets:new(),
send_timer=TRef,
counter=1}}.

%%--------------------------------------------------------------------
%% Function: handle_call/3
%% Description: Handling call messages
%% Returns: {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} | (terminate/2 is called)
%% {stop, Reason, State} (terminate/2 is called)
%%--------------------------------------------------------------------
handle_call(Request, From, State) ->
Reply = ok,
{reply, Reply, State}.

%%--------------------------------------------------------------------
%% Function: handle_cast/2
%% Description: Handling cast messages
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%--------------------------------------------------------------------
handle_cast({send_heartbeat}, State) ->
send_heartbeat(State),
NewState = State#state{counter = State#state.counter + 1},
{noreply, NewState};
handle_cast(Msg, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: handle_info/2
%% Description: Handling all non call/cast messages
%% Returns: {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%--------------------------------------------------------------------
handle_info({udp, Socket, IP, InPortNo, Packet}, State) ->
{node_name, Node,
counter, Counter} = binary_to_term(Packet),
io:format("received packet ~p from node ~p~n",[Counter, Node]),
{noreply, State};
handle_info(Info, State) ->
{noreply, State}.

%%--------------------------------------------------------------------
%% Function: terminate/2
%% Description: Shutdown the server
%% Returns: any (ignored by gen_server)
%%--------------------------------------------------------------------
terminate(Reason, State) ->
ok.

%%--------------------------------------------------------------------
%% Func: code_change/3
%% Purpose: Convert process state when code is changed
%% Returns: {ok, NewState}
%%--------------------------------------------------------------------
code_change(OldVsn, State, Extra) ->
{ok, State}.

%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
trigger_heartbeat() ->
gen_server:cast(?SERVER, {send_heartbeat}).

send_heartbeat(State) ->
Packet = {node_name, node(),
counter, State#state.counter},
ok = gen_udp:send(State#state.socket,
get_addr(),
get_port(),
term_to_binary(Packet)).

get_addr() ->
case application:get_application() of
undefined ->
?ADDR;
{ok, App} ->
case application:get_env(App, addr) of
undefined ->
?ADDR;
{ok, Val} ->
Val
end
end.

get_port() ->
case application:get_application() of
undefined ->
?PORT;
{ok, App} ->
case application:get_env(App, port) of
undefined ->
?PORT;
{ok, Val} ->
Val
end
end.

get_period() ->
case application:get_application() of
undefined ->
?HB_PERIOD_MS;
{ok, App} ->
case application:get_env(App, period) of
undefined ->
?HB_PERIOD_MS;
{ok, Val} ->
Val
end
end.


%%--------------------------------------------------------------------
%%% debug functions
%%--------------------------------------------------------------------
run() ->
{ok, Pid} = ?MODULE:start_link(),
io:format("Running for 5 minutes.~n",[]),
timer:sleep(5*60*1000),
io:format("done.~n",[]).

#

On Sep 2, 2004, at 12:39 PM, Reto Kramer wrote:

> The following works on the OSX and Linux for me. I had trouble
> opening the multicast socket on WinXP, but no patience to figure out
> the cause.
>
> cheers,
> - Reto
>
> Open a multicast port with:
> Res = gen_udp:open(get_port(), [binary,
> {reuseaddr,true},
> {ip,get_addr()},
> {multicast_loop,true},
> {add_membership,{get_addr(),
> {0,0,0,0}}}]),
>
> where
> get_addr() ->
> {ok, App} = application:get_application(),
> case application:get_env(App, addr) of
> {ok, Val} ->
> Val;
> undefined ->
> ?ADDR
> end.
> get_port() -> ...
>
> and the env key of the .app file is
> {env, [{addr, {239,0,0,1}}, % the multicast ip addr
> {port, 10042}, % the port we multicast at
> {period, 1000}]}, % heartbeat interval in ms
>
> Send packets with
> Packet = {node_name, node()},
> ok = gen_udp:send(State#state.socket,
> get_addr(),
> get_port(),
> term_to_binary(Packet)),
>
> and receive packets like this:
> receive
> {udp, Socket, IP, InPortNo, Packet} ->
> {node_name, Node} = binary_to_term(Packet),
>
> #
>
> On Sep 2, 2004, at 12:03 PM, Martin J. Logan wrote:
>
>> Is it possible to have multiple nodes on a single machine listening
>> for
>> the same multicast packets at the same time? How can this be
>> accomplished within erts?
>>
>> Cheers,
>> Martin
>>
>



Post generated using Mail2Forum (http://m2f.sourceforge.net)
mlogan at futuresource.co
Posted: Fri Sep 03, 2004 2:46 pm Reply with quote
Guest
Reto, again thank you very much for the help. I am not sure what is
going on but on my machine, running Fedora Core 2 kernel 2.4.20-8, the
nodes eat eachothers packets.


received packet 1 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 2 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 3 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 4 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 5 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 6 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 7 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 8 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 9 from node 'bar_at_dhcp-lom-194-186.futuresource.com'


received packet 10 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 1 from node 'foo_at_dhcp-lom-194-186.futuresource.com'
received packet 11 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 2 from node 'foo_at_dhcp-lom-194-186.futuresource.com'
received packet 12 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 3 from node 'foo_at_dhcp-lom-194-186.futuresource.com'
received packet 13 from node 'bar_at_dhcp-lom-194-186.futuresource.com'
received packet 4 from node 'foo_at_dhcp-lom-194-186.futuresource.com'
received packet 14 from node 'bar_at_dhcp-lom-194-186.futuresource.com'

Once the second node foo starts receiving packets then bar stops.
Strange...

Martin



On Thu, 2004-09-02 at 20:58, Reto Kramer wrote:
> [ups, sent this from wrong account initially]
>
> Martin,
>
> Here's a complete testcase that you can run locally. It's a dumbed down
> version of a larget app.
>
> Compile this file and then run it in two terminals with:
>
> erl -sname foo -s discover_server run
> erl -sname bar -s discover_server run
>
> Each node (foo and bar) will send numbered heartbeats to the multicast
> address and each one will pick up it's own packets as well as packets
> send by the other node.
>
> (foo_at_yoghurt)1> Running for 5 minutes.
> received packet 1 from node foo_at_yoghurt
> received packet 2 from node foo_at_yoghurt
> received packet 1 from node bar_at_yoghurt
> received packet 3 from node foo_at_yoghurt
> received packet 2 from node bar_at_yoghurt
> received packet 4 from node foo_at_yoghurt
> received packet 3 from node bar_at_yoghurt
> received packet 5 from node foo_at_yoghurt
>
> (bar_at_yoghurt)1> Running for 5 minutes.
> received packet 2 from node foo_at_yoghurt
> received packet 1 from node bar_at_yoghurt
> received packet 3 from node foo_at_yoghurt
> received packet 2 from node bar_at_yoghurt
> received packet 4 from node foo_at_yoghurt
> received packet 3 from node bar_at_yoghurt
>
> This is running on one OSX box. E.g. foo picks up it's own heartbeat
> 2, and bar picks up that same packet (foo's heartbeat 2) as well. So
> here they are not eating each others packets, but each process sees the
> same packets.
>
> Run it to see what you'll get on your setup.
>
> cheers,
> - Reto
>
> %%%-------------------------------------------------------------------
> %%% File : discover_server.erl
> %%% Author : reto <kramer_at_acm.org>
> %%% Description : Basic multicast based heart-beating
> %%%-------------------------------------------------------------------
> -module(discover_server).
>
> -behaviour(gen_server).
> %%--------------------------------------------------------------------
> %% Include files
> %%--------------------------------------------------------------------
>
> %%--------------------------------------------------------------------
> %% External exports
> -export([start_link/0]).
>
> -export([run/0]).
>
> -export([trigger_heartbeat/0]).
>
> %% gen_server callbacks
> -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
> terminate/2, code_change/3]).
>
> -record(state, {socket, % multicast udp socket
> nodes, % set of nodes (atoms)
> send_timer, % timer used to send heartbeats
> counter
> }).
>
> -define(HB_PERIOD_MS, 1000). % (if not in .app) default hb interval
> -define(ADDR, {239,0,42,1}). % (if not in .app) default addr
> -define(PORT, 10042). % (if not in .app) default port
>
> -define(SERVER, ?MODULE).
>
> %%====================================================================
> %% External functions
> %%====================================================================
> %%--------------------------------------------------------------------
> %% Function: start_link/0
> %% Description: Starts the server
> %%--------------------------------------------------------------------
> start_link() ->
> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
>
> %%====================================================================
> %% Server functions
> %%====================================================================
>
> %%--------------------------------------------------------------------
> %% Function: init/1
> %% Description: Initiates the server
> %% Returns: {ok, State} |
> %% {ok, State, Timeout} |
> %% ignore |
> %% {stop, Reason}
> %%--------------------------------------------------------------------
> init([]) ->
> process_flag(trap_exit, true),
> {ok, Socket} = gen_udp:open(get_port(), [binary,
> {reuseaddr,true},
> {ip,get_addr()},
> {multicast_loop,true},
> {add_membership,{get_addr(),
> {0,0,0,0}}}]),
> % net_kernel:monitor_nodes(true),
> {ok, TRef} = timer:apply_interval(get_period(),
> ?MODULE, trigger_heartbeat, []),
> {ok, #state{socket=Socket,
> nodes=sets:new(),
> send_timer=TRef,
> counter=1}}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_call/3
> %% Description: Handling call messages
> %% Returns: {reply, Reply, State} |
> %% {reply, Reply, State, Timeout} |
> %% {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, Reply, State} | (terminate/2 is called)
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_call(Request, From, State) ->
> Reply = ok,
> {reply, Reply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_cast/2
> %% Description: Handling cast messages
> %% Returns: {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_cast({send_heartbeat}, State) ->
> send_heartbeat(State),
> NewState = State#state{counter = State#state.counter + 1},
> {noreply, NewState};
> handle_cast(Msg, State) ->
> {noreply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_info/2
> %% Description: Handling all non call/cast messages
> %% Returns: {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_info({udp, Socket, IP, InPortNo, Packet}, State) ->
> {node_name, Node,
> counter, Counter} = binary_to_term(Packet),
> io:format("received packet ~p from node ~p~n",[Counter, Node]),
> {noreply, State};
> handle_info(Info, State) ->
> {noreply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: terminate/2
> %% Description: Shutdown the server
> %% Returns: any (ignored by gen_server)
> %%--------------------------------------------------------------------
> terminate(Reason, State) ->
> ok.
>
> %%--------------------------------------------------------------------
> %% Func: code_change/3
> %% Purpose: Convert process state when code is changed
> %% Returns: {ok, NewState}
> %%--------------------------------------------------------------------
> code_change(OldVsn, State, Extra) ->
> {ok, State}.
>
> %%--------------------------------------------------------------------
> %%% Internal functions
> %%--------------------------------------------------------------------
> trigger_heartbeat() ->
> gen_server:cast(?SERVER, {send_heartbeat}).
>
> send_heartbeat(State) ->
> Packet = {node_name, node(),
> counter, State#state.counter},
> ok = gen_udp:send(State#state.socket,
> get_addr(),
> get_port(),
> term_to_binary(Packet)).
>
> get_addr() ->
> case application:get_application() of
> undefined ->
> ?ADDR;
> {ok, App} ->
> case application:get_env(App, addr) of
> undefined ->
> ?ADDR;
> {ok, Val} ->
> Val
> end
> end.
>
> get_port() ->
> case application:get_application() of
> undefined ->
> ?PORT;
> {ok, App} ->
> case application:get_env(App, port) of
> undefined ->
> ?PORT;
> {ok, Val} ->
> Val
> end
> end.
>
> get_period() ->
> case application:get_application() of
> undefined ->
> ?HB_PERIOD_MS;
> {ok, App} ->
> case application:get_env(App, period) of
> undefined ->
> ?HB_PERIOD_MS;
> {ok, Val} ->
> Val
> end
> end.
>
>
> %%--------------------------------------------------------------------
> %%% debug functions
> %%--------------------------------------------------------------------
> run() ->
> {ok, Pid} = ?MODULE:start_link(),
> io:format("Running for 5 minutes.~n",[]),
> timer:sleep(5*60*1000),
> io:format("done.~n",[]).
>
> #
>
> On Sep 2, 2004, at 12:39 PM, Reto Kramer wrote:
>
> > The following works on the OSX and Linux for me. I had trouble
> > opening the multicast socket on WinXP, but no patience to figure out
> > the cause.
> >
> > cheers,
> > - Reto
> >
> > Open a multicast port with:
> > Res = gen_udp:open(get_port(), [binary,
> > {reuseaddr,true},
> > {ip,get_addr()},
> > {multicast_loop,true},
> > {add_membership,{get_addr(),
> > {0,0,0,0}}}]),
> >
> > where
> > get_addr() ->
> > {ok, App} = application:get_application(),
> > case application:get_env(App, addr) of
> > {ok, Val} ->
> > Val;
> > undefined ->
> > ?ADDR
> > end.
> > get_port() -> ...
> >
> > and the env key of the .app file is
> > {env, [{addr, {239,0,0,1}}, % the multicast ip addr
> > {port, 10042}, % the port we multicast at
> > {period, 1000}]}, % heartbeat interval in ms
> >
> > Send packets with
> > Packet = {node_name, node()},
> > ok = gen_udp:send(State#state.socket,
> > get_addr(),
> > get_port(),
> > term_to_binary(Packet)),
> >
> > and receive packets like this:
> > receive
> > {udp, Socket, IP, InPortNo, Packet} ->
> > {node_name, Node} = binary_to_term(Packet),
> >
> > #
> >
> > On Sep 2, 2004, at 12:03 PM, Martin J. Logan wrote:
> >
> >> Is it possible to have multiple nodes on a single machine listening
> >> for
> >> the same multicast packets at the same time? How can this be
> >> accomplished within erts?
> >>
> >> Cheers,
> >> Martin
> >>
> >



Post generated using Mail2Forum (http://m2f.sourceforge.net)
mlogan at futuresource.co
Posted: Fri Sep 03, 2004 2:51 pm Reply with quote
Guest
Disregard the last email - In my eagerness to try this last example I
plugged in the wrong IP for the multicast. I was using the localhost IP
addr which of course explains the round robin in the last case. Thanks
for the help - it works perfectly.


On Thu, 2004-09-02 at 20:58, Reto Kramer wrote:
> [ups, sent this from wrong account initially]
>
> Martin,
>
> Here's a complete testcase that you can run locally. It's a dumbed down
> version of a larget app.
>
> Compile this file and then run it in two terminals with:
>
> erl -sname foo -s discover_server run
> erl -sname bar -s discover_server run
>
> Each node (foo and bar) will send numbered heartbeats to the multicast
> address and each one will pick up it's own packets as well as packets
> send by the other node.
>
> (foo_at_yoghurt)1> Running for 5 minutes.
> received packet 1 from node foo_at_yoghurt
> received packet 2 from node foo_at_yoghurt
> received packet 1 from node bar_at_yoghurt
> received packet 3 from node foo_at_yoghurt
> received packet 2 from node bar_at_yoghurt
> received packet 4 from node foo_at_yoghurt
> received packet 3 from node bar_at_yoghurt
> received packet 5 from node foo_at_yoghurt
>
> (bar_at_yoghurt)1> Running for 5 minutes.
> received packet 2 from node foo_at_yoghurt
> received packet 1 from node bar_at_yoghurt
> received packet 3 from node foo_at_yoghurt
> received packet 2 from node bar_at_yoghurt
> received packet 4 from node foo_at_yoghurt
> received packet 3 from node bar_at_yoghurt
>
> This is running on one OSX box. E.g. foo picks up it's own heartbeat
> 2, and bar picks up that same packet (foo's heartbeat 2) as well. So
> here they are not eating each others packets, but each process sees the
> same packets.
>
> Run it to see what you'll get on your setup.
>
> cheers,
> - Reto
>
> %%%-------------------------------------------------------------------
> %%% File : discover_server.erl
> %%% Author : reto <kramer_at_acm.org>
> %%% Description : Basic multicast based heart-beating
> %%%-------------------------------------------------------------------
> -module(discover_server).
>
> -behaviour(gen_server).
> %%--------------------------------------------------------------------
> %% Include files
> %%--------------------------------------------------------------------
>
> %%--------------------------------------------------------------------
> %% External exports
> -export([start_link/0]).
>
> -export([run/0]).
>
> -export([trigger_heartbeat/0]).
>
> %% gen_server callbacks
> -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
> terminate/2, code_change/3]).
>
> -record(state, {socket, % multicast udp socket
> nodes, % set of nodes (atoms)
> send_timer, % timer used to send heartbeats
> counter
> }).
>
> -define(HB_PERIOD_MS, 1000). % (if not in .app) default hb interval
> -define(ADDR, {239,0,42,1}). % (if not in .app) default addr
> -define(PORT, 10042). % (if not in .app) default port
>
> -define(SERVER, ?MODULE).
>
> %%====================================================================
> %% External functions
> %%====================================================================
> %%--------------------------------------------------------------------
> %% Function: start_link/0
> %% Description: Starts the server
> %%--------------------------------------------------------------------
> start_link() ->
> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
>
> %%====================================================================
> %% Server functions
> %%====================================================================
>
> %%--------------------------------------------------------------------
> %% Function: init/1
> %% Description: Initiates the server
> %% Returns: {ok, State} |
> %% {ok, State, Timeout} |
> %% ignore |
> %% {stop, Reason}
> %%--------------------------------------------------------------------
> init([]) ->
> process_flag(trap_exit, true),
> {ok, Socket} = gen_udp:open(get_port(), [binary,
> {reuseaddr,true},
> {ip,get_addr()},
> {multicast_loop,true},
> {add_membership,{get_addr(),
> {0,0,0,0}}}]),
> % net_kernel:monitor_nodes(true),
> {ok, TRef} = timer:apply_interval(get_period(),
> ?MODULE, trigger_heartbeat, []),
> {ok, #state{socket=Socket,
> nodes=sets:new(),
> send_timer=TRef,
> counter=1}}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_call/3
> %% Description: Handling call messages
> %% Returns: {reply, Reply, State} |
> %% {reply, Reply, State, Timeout} |
> %% {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, Reply, State} | (terminate/2 is called)
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_call(Request, From, State) ->
> Reply = ok,
> {reply, Reply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_cast/2
> %% Description: Handling cast messages
> %% Returns: {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_cast({send_heartbeat}, State) ->
> send_heartbeat(State),
> NewState = State#state{counter = State#state.counter + 1},
> {noreply, NewState};
> handle_cast(Msg, State) ->
> {noreply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: handle_info/2
> %% Description: Handling all non call/cast messages
> %% Returns: {noreply, State} |
> %% {noreply, State, Timeout} |
> %% {stop, Reason, State} (terminate/2 is called)
> %%--------------------------------------------------------------------
> handle_info({udp, Socket, IP, InPortNo, Packet}, State) ->
> {node_name, Node,
> counter, Counter} = binary_to_term(Packet),
> io:format("received packet ~p from node ~p~n",[Counter, Node]),
> {noreply, State};
> handle_info(Info, State) ->
> {noreply, State}.
>
> %%--------------------------------------------------------------------
> %% Function: terminate/2
> %% Description: Shutdown the server
> %% Returns: any (ignored by gen_server)
> %%--------------------------------------------------------------------
> terminate(Reason, State) ->
> ok.
>
> %%--------------------------------------------------------------------
> %% Func: code_change/3
> %% Purpose: Convert process state when code is changed
> %% Returns: {ok, NewState}
> %%--------------------------------------------------------------------
> code_change(OldVsn, State, Extra) ->
> {ok, State}.
>
> %%--------------------------------------------------------------------
> %%% Internal functions
> %%--------------------------------------------------------------------
> trigger_heartbeat() ->
> gen_server:cast(?SERVER, {send_heartbeat}).
>
> send_heartbeat(State) ->
> Packet = {node_name, node(),
> counter, State#state.counter},
> ok = gen_udp:send(State#state.socket,
> get_addr(),
> get_port(),
> term_to_binary(Packet)).
>
> get_addr() ->
> case application:get_application() of
> undefined ->
> ?ADDR;
> {ok, App} ->
> case application:get_env(App, addr) of
> undefined ->
> ?ADDR;
> {ok, Val} ->
> Val
> end
> end.
>
> get_port() ->
> case application:get_application() of
> undefined ->
> ?PORT;
> {ok, App} ->
> case application:get_env(App, port) of
> undefined ->
> ?PORT;
> {ok, Val} ->
> Val
> end
> end.
>
> get_period() ->
> case application:get_application() of
> undefined ->
> ?HB_PERIOD_MS;
> {ok, App} ->
> case application:get_env(App, period) of
> undefined ->
> ?HB_PERIOD_MS;
> {ok, Val} ->
> Val
> end
> end.
>
>
> %%--------------------------------------------------------------------
> %%% debug functions
> %%--------------------------------------------------------------------
> run() ->
> {ok, Pid} = ?MODULE:start_link(),
> io:format("Running for 5 minutes.~n",[]),
> timer:sleep(5*60*1000),
> io:format("done.~n",[]).
>
> #
>
> On Sep 2, 2004, at 12:39 PM, Reto Kramer wrote:
>
> > The following works on the OSX and Linux for me. I had trouble
> > opening the multicast socket on WinXP, but no patience to figure out
> > the cause.
> >
> > cheers,
> > - Reto
> >
> > Open a multicast port with:
> > Res = gen_udp:open(get_port(), [binary,
> > {reuseaddr,true},
> > {ip,get_addr()},
> > {multicast_loop,true},
> > {add_membership,{get_addr(),
> > {0,0,0,0}}}]),
> >
> > where
> > get_addr() ->
> > {ok, App} = application:get_application(),
> > case application:get_env(App, addr) of
> > {ok, Val} ->
> > Val;
> > undefined ->
> > ?ADDR
> > end.
> > get_port() -> ...
> >
> > and the env key of the .app file is
> > {env, [{addr, {239,0,0,1}}, % the multicast ip addr
> > {port, 10042}, % the port we multicast at
> > {period, 1000}]}, % heartbeat interval in ms
> >
> > Send packets with
> > Packet = {node_name, node()},
> > ok = gen_udp:send(State#state.socket,
> > get_addr(),
> > get_port(),
> > term_to_binary(Packet)),
> >
> > and receive packets like this:
> > receive
> > {udp, Socket, IP, InPortNo, Packet} ->
> > {node_name, Node} = binary_to_term(Packet),
> >
> > #
> >
> > On Sep 2, 2004, at 12:03 PM, Martin J. Logan wrote:
> >
> >> Is it possible to have multiple nodes on a single machine listening
> >> for
> >> the same multicast packets at the same time? How can this be
> >> accomplished within erts?
> >>
> >> Cheers,
> >> Martin
> >>
> >



Post generated using Mail2Forum (http://m2f.sourceforge.net)
wuji
Posted: Mon Sep 17, 2012 1:38 am Reply with quote
User Joined: 10 Aug 2012 Posts: 654
also vowed that he would teach others how to be be cheap real jordans be healthy. He even had the Roman numerals I, C,
M, X, C and M tattooed onto his side. The The designer replica *beep* The last three are topped by horizontal lines, which means
base numbers should be multiplied by 1,000, so in Arabic Arabic [h3]replica designer *beep*[/h3] Arabic numerals, they read 1, 100, 500, 1,000, 10,000, 100,000
1,000,000.Powell said it symbolizes how many people have thanked him him cheap replica *beep* him for making a positive change in their lives."I think
all have a desire to feel significant in the world," world," cheap real jordans world," he said. "It's not about me doing nice things
other people. I get something out of this, and its its cheap jordans for sale its fulfillment. This is the best addiction in the world."Lou
View user's profile Send private message
mbtshoes88
Posted: Wed Sep 19, 2012 9:22 am Reply with quote
User Joined: 18 Sep 2012 Posts: 30
Acquiring the true blessing with the public isn’t necessarily straightforward. Organisations consequently have to Cheap Franklin & Marshall use a lot more efforts so as to bring your showcase of these Franklin & Marshall Online intended likely prospective buyers. These products allocate a tremendous provide advertising so that you Franklin & Marshall Clothing can deliver possibility shoppers. However, don’t assume Franklin & Marshall Hoodie Sweatshirt all businesses Franklin & Marshall Man have a similar determined expenditures just for saying. Franklin & Marshall Women When there is businesses that could commit a large amount meant for build-up, many only need important resources.The effective use of tailor made embellished products and Franklin and Marshall services, for instance a long sleeve polo top, provides a new on a good buy choice to get promoting an Franklin & Marshall Shirts online business. Compared with Cheap Franklin Marshall using billboards and / or tarpaulins, these kind of Franklin & Marshall Hoodies physical objects Franklin & Marshall Tracksuit will need trifling investment. These have granted companies a highly effective method for campaigning their products and services or products. By just applying 2012 Franklin & Marshall their management and business Franklin & Marshall Outlet company name or simply system,2012 franklin Cheap Franklin and Marshall & marshall Franklin & Marshall Jackets outlet online, it’s probably for Franklin & Marshall Sale them to get a new customer.
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum