Beginner OTP question
Scott Lystig Fritchie
fritchie@REDACTED
Fri Feb 18 07:30:00 CET 2005
Here's a unified diff for one way (of several) to fix things up. I
removed the bits trying to use global naming service.
--- myserver.erl Thu Feb 17 23:29:49 2005
+++ myserver2.erl Thu Feb 17 23:28:56 2005
@@ -2,16 +2,16 @@
-behaviour(gen_server).
--export([start/0, init/1, send/0, handle_call/3]).
+-export([start/0, init/1, send/1, handle_call/3]).
start() ->
- gen_server:start({global, myserver}, myserver, [], []).
+ gen_server:start({local, myserver}, myserver, [], []).
init(_Args) ->
{ok, ""}.
-send() ->
- gen_server:call(myserver, send).
+send(ServerID) ->
+ gen_server:call(ServerID, send).
handle_call(send, From, _State) ->
io:format("send called from ~p", [From]),
Then, over on the gbye node, use this function call:
myserver:send({myserver, hello@REDACTED}).
On the hello node, you can use:
myserver:send(myserver).
myserver:send({myserver, node()}).
myserver:send({myserver, hello@REDACTED}).
If you'd started the server on hello using:
{ok, MyServerPid} = myserver:start().
Then this would work, too:
myserver:send(MyServerPid).
Using the list_to_pid() function is generally frowned upon. Joe
Armstrong would say that it allows you to violate the principle of a
process's "unforgeable name", namely its process ID number. If you're
not using a local naming scheme (as shown above) or a global naming
scheme, either of which maps a well-known name to a process ID, the
only way you're supposed to know a process ID is if someone else tells
you what it is. list_to_pid() allows you to circumvent it.
One handy trick with the shell is using the history mechanism. Here,
at command number 12, I started the server but forgot to save the
pid. But I can easily get the real, honest-to-goodness pid after the
fact.
(a@REDACTED)12> myserver:start().
{ok,<0.56.0>}
(a@REDACTED)13> {ok, MyServerPid} = v(12).
{ok,<0.56.0>}
(a@REDACTED)14> myserver:send(MyServerPid).
send called from {<0.50.0>,#Ref<0.0.0.94>}"Thanks for calling"
In practice, you need someone with a well-known name to act as an
introducer to help break the ice.(*) Otherwise, you wouldn't be able to
communicate with anyone: you wouldn't know any pids at all!
If over on the gbye node you said:
(gbye@REDACTED)13> register(a_local_name, self()).
true
... then the shell over on the hello node can easily send messages to
the shell on gbye. On the hello node, use:
(hello@REDACTED)17> {a_local_name, gbye@REDACTED} ! {ice_breaker, MyServerPid}.
{ice_breaker,<0.56.0>}
That uses the "!" notation to send a simple message over to
a_local_name over on gbye@REDACTED(**)
That message is waiting in the shell process's mailbox over on the
other node. You can fetch it by:
(gbye@REDACTED)19> receive {ice_breaker, Pid} -> Pid end.
<6348.56.0>
And then you can use it to call your gen_server process without
relying on the local name registration scheme.
(gbye@REDACTED)20> myserver:send(Pid).
"Thanks for calling"
You can do this same message passing stuff between Erlang nodes
running on different UNIX/Windows/Mac/whatever machines.(****)
-Scott
(*) The only other way would be some kind of side communication
channel. For example, if you could write a pid to a file and then
have some other process read the file to get that pid.
(**) "!" is not used to call a function, like you'd tried to do. "!"
is the Erlang primitive to send a message to another process.
The gen_server:call() function ends up using this notation to
send the message, but it hides some additional details from you. So
does the gen_server code receiving side. When using gen_server, you
usually don't need to know the details.
(***) I dunno where this file lives on a Windows platform, sorry.
(****) It's common to run into a problem with an Erlang security
mechanism: there's a file called ".erlang.cookie" that's placed in
your UNIX home directory(***). If your machines don't have a common
home directory (e.g. via NFS), then you'll have to copy one machine's
".erlang.cookie" file over to the other machine, then restart both
Erlang nodes.
More information about the erlang-questions
mailing list