Quantcast

Help! with gen_server and a chat_server

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Help! with gen_server and a chat_server

megalomania
This post has NOT been accepted by the mailing list yet.
Hi all,
Im newbie on Erlang and trying lear to use gen_server but i begin to understan that maybe im wrong.

Im just trying to making a chat_server with gen_serve, so the idea is a client on an another node could try to login in the chat_server who will be in another node.

here is my code:


-module(servidor) .
-behavior(gen_server) .

% API functions
-export([start_link/0, hi/0, login/2, logout/1, times/2, stop/0]).

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

-define(NAME_SERVER, ?MODULE).
-define(LOGUEADOS, logeados).


start_link() ->
        gen_server:start_link({local, ?NAME_SERVER}, ?MODULE, [], []).%Se registra el proceso con el nombre del modulo(servidor)

hi() ->
        gen_server:cast(?MODULE, hi) .

stop() ->
        gen_server:cast(?MODULE, stop).

login(Nick,Pid) ->
        gen_server:call(?MODULE, {login, Nick, Pid}).

logout(Nick) ->
        gen_server:call(?MODULE, {logout, Nick}).

times(N, M) ->
        ?MODULE ! {times_request, self(), {N, M}}.



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Callback functions implementation %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

init([]) ->
        {ok, ets:new(?LOGUEADOS, [set])}.

terminate(_Reason, _State) ->
        {_, Tab} = _State,
        ets:delete(Tab),
        ok.


handle_call({login, Nick, Pid}, _From, _State) ->
        %% En el login habra que crear una nodo del que haga el login // Para probarlo, miro simplemente si existe en la BD.
        io:format("Loggin.. y state=~w: ~n", [_State]),
        BOOL = ets:member(_State, Nick),
        io:format("The user is online? = ~w ~n", [BOOL]),
        if
                BOOL == true -> io:format("~w its already login", [Nick]);
                true -> ets:insert(_State, {Nick,Pid}), io:format("Login succesful ~n")
        end,
        {reply, {login, Nick}, _State};


handle_call({logout, Nick}, _From, _State) ->
        io:format("Logout...~n", []),
        ets:delete(_State, Nick).


handle_cast(hi, State) ->
        io:fwrite("\t\tHi!\~n"),
        {noreply, State} ;

handle_cast(stop, _State) ->
        io:format("Stopped~n", []),
        {_, Tab} = _State,
        ets:delete(Tab),
        {stop, normal, _State} .

       
handle_info({times_request, Pid, {N, M}}, State) ->
        io:fwrite("\t~w server handling info, request number ~w~n", [?MODULE, State]),
        Pid ! {times_response, N*M},
        {noreply, State} .

code_change(_OldVsn, _State, _Extra) ->
        {ok, _State}.


and then i typed this in one console:

>erl -sname server
(server@ubuntuPC)1> c(servidor).
{ok,servidor}
(server@ubuntuPC)2> servidor:start_link().
{ok,<0.45.0>}
(server@ubuntuPC)3>      


and then i typed this in another console:
user@ubuntuPC)25> {servidor,server@ubuntuPC} ! {servidor,login,irene,777}.          {servidor,login,irene,777}
(user@ubuntuPC)26> {servidor,server@ubuntuPC} ! {servidor,login,irene,777}.
{servidor,login,irene,777}
(user@ubuntuPC)27> {servidor,server@ubuntuPC} ! servidor:call(login,irene,6666).
** exception error: undefined function servidor:call/3
(user@ubuntuPC)28> {servidor,server@ubuntuPC} ! servidor:login(irene,6666).        
** exception exit: {noproc,{gen_server,call,[servidor,{login,irene,6666}]}}
     in function  gen_server:call/2
(user@ubuntuPC)29> {servidor,server@ubuntuPC} ! process_request(login,{irene,2321}).
** exception error: undefined shell command process_request/2
(user@ubuntuPC)30> {servidor,server@ubuntuPC} ! {hi}.                              
{hi}
(user@ubuntuPC)31> {servidor,server@ubuntuPC} ! {async,hi}.


almost or the most of instructions makes server_node crash :(

My question is, what im doing wrong? It is the correct way?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Help! with gen_server and a chat_server

Mike Oxford-2
Unfortunately there are quite a number of things wrong. =(

You should read this:
http://www.erlang.org/doc/getting_started/conc_prog.html
I would suggest going through the tutorial on  http://learnyousomeerlang.com .
 It's quite good.

Here's why your code crashed...

*(user)27> {servidor,server} !*
*servidor:call(login,irene,6666).
** exception error: undefined function servidor:call/3
*
You told it to call servidor:call/3, but that does not exist.  You should
be using gen_server:call/2 (see below). If it did, it would make the call
and try to send the return code to  *{servidor,server}* *.*
*
*
*(user)28> {servidor,server} ! servidor:login(irene,6666).
** exception exit: {noproc,{gen_server,call,[servidor,{login,irene,6666}]}}
    in function  gen_server:call/2
*
You now called servidor:login/2 locally, which worked but tried to
gen_server:call back to itself (via ?MODULE) to do a login.  However,
servidor is not running on  *(user)* ... it's running on *
{servidor,server}*

*(user)29> {servidor,server} !
process_request(login,{irene,2321}).
** exception error: undefined shell command process_request/2
*
You ran this from the shell and it doesn't know about process_request/2.
 If it did, the return-value from process_request would be shipped to *
 {servidor,server}*

Don't mix ! and call/cast.    The receive handlers are slightly different
for OTP stuff ({'$gen_cast',Msg,State} and {'$gen_call',From,Msg,State})
which you have to account for.
If you're using OTP, use OTP calls and handlers.  It's cleaner.

Try gen_server:call( {servidor,server}, {login, irene,777} ).

Make sure server can login from server  ( such as gen_server:call(self(),
{login, irene, 777} ... and then scale out to multiple nodes.)

-mox


On Wed, Apr 11, 2012 at 4:03 PM, megalomania <ricardocb48> wrote:

> *Hi all,
> Im newbie on Erlang and trying lear to use gen_server but i begin to
> understan that maybe im wrong.
>
> Im just trying to making a chat_server with gen_serve, so the idea is a
> client on an another node could try to login in the chat_server who will be
> in another node.
>
> here is my code:
> *
>
> -module(servidor) .
> -behavior(gen_server) .
>
> % API functions
> -export([start_link/0, hi/0, login/2, logout/1, times/2, stop/0]).
>
> % Callback functions
> -export([init/1, handle_call/3, handle_info/2, terminate/2, handle_cast/2,
> code_change/3]).
>
> -define(NAME_SERVER, ?MODULE).
> -define(LOGUEADOS, logeados).
>
>
> start_link() ->
>        gen_server:start_link({local, ?NAME_SERVER}, ?MODULE, [], []).%Se
> registra
> el proceso con el nombre del modulo(servidor)
>
> hi() ->
>        gen_server:cast(?MODULE, hi) .
>
> stop() ->
>        gen_server:cast(?MODULE, stop).
>
> login(Nick,Pid) ->
>        gen_server:call(?MODULE, {login, Nick, Pid}).
>
> logout(Nick) ->
>        gen_server:call(?MODULE, {logout, Nick}).
>
> times(N, M) ->
>        ?MODULE ! {times_request, self(), {N, M}}.
>
>
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Callback functions implementation %%
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> init([]) ->
>        {ok, ets:new(?LOGUEADOS, [set])}.
>
> terminate(_Reason, _State) ->
>        {_, Tab} = _State,
>        ets:delete(Tab),
>        ok.
>
>
> handle_call({login, Nick, Pid}, _From, _State) ->
>        %% En el login habra que crear una nodo del que haga el login //
> Para
> probarlo, miro simplemente si existe en la BD.
>        io:format("Loggin.. y state=~w: ~n", [_State]),
>        BOOL = ets:member(_State, Nick),
>        io:format("The user is online? = ~w ~n", [BOOL]),
>        if
>                BOOL == true -> io:format("~w its already login", [Nick]);
>                true -> ets:insert(_State, {Nick,Pid}), io:format("Login
> succesful ~n")
>        end,
>        {reply, {login, Nick}, _State};
>
>
> handle_call({logout, Nick}, _From, _State) ->
>        io:format("Logout...~n", []),
>        ets:delete(_State, Nick).
>
>
> handle_cast(hi, State) ->
>        io:fwrite("\t\tHi!\~n"),
>        {noreply, State} ;
>
> handle_cast(stop, _State) ->
>        io:format("Stopped~n", []),
>        {_, Tab} = _State,
>        ets:delete(Tab),
>        {stop, normal, _State} .
>
>
> handle_info({times_request, Pid, {N, M}}, State) ->
>        io:fwrite("\t~w server handling info, request number ~w~n",
> [?MODULE,
> State]),
>        Pid ! {times_response, N*M},
>        {noreply, State} .
>
> code_change(_OldVsn, _State, _Extra) ->
>        {ok, _State}.
>
>
> *and then i typed this in one console:*
>
> >erl -sname server
> (server)1> c(servidor).
> {ok,servidor}
> (server)2> servidor:start_link().
> {ok,<0.45.0>}
> (server)3>
>
>
> *and then i typed this in another console:*
> user)25> {servidor,server} ! {servidor,login,irene,777}.
> {servidor,login,irene,777}
> (user)26> {servidor,server} !
> {servidor,login,irene,777}.
> {servidor,login,irene,777}
> (user)27> {servidor,server} !
> servidor:call(login,irene,6666).
> ** exception error: undefined function servidor:call/3
> (user)28> {servidor,server} !
> servidor:login(irene,6666).
> ** exception exit: {noproc,{gen_server,call,[servidor,{login,irene,6666}]}}
>     in function  gen_server:call/2
> (user)29> {servidor,server} !
> process_request(login,{irene,2321}).
> ** exception error: undefined shell command process_request/2
> (user)30> {servidor,server} ! {hi}.
> {hi}
> (user)31> {servidor,server} ! {async,hi}.
>
>
> *almost or the most of instructions makes server_node crash :(*
>
> My question is, what im doing wrong? It is the correct way?
>
>
> --
> View this message in context:
> http://erlang.2086793.n4.nabble.com/Help-with-gen-server-and-a-chat-server-tp4550462p4550462.html
> Sent from the Erlang Questions mailing list archive at Nabble.com.
> _______________________________________________
> erlang-questions mailing list
> erlang-questions
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20120411/b021f2c9/attachment.html>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Help! with gen_server and a chat_server

Bengt Kleberg-4
In reply to this post by megalomania
Greetings,

Your first crash is the function call
servidor:call(login,irene,6666).

I do not see such a function in the servidor module. Perhaps you have
forgotten to add it?

After that crash your process is dead (you are linked to it) and nothing
will work.


bengt

On Thu, 2012-04-12 at 01:03 +0200, megalomania wrote:

> *Hi all,
> Im newbie on Erlang and trying lear to use gen_server but i begin to
> understan that maybe im wrong.
>
> Im just trying to making a chat_server with gen_serve, so the idea is a
> client on an another node could try to login in the chat_server who will be
> in another node.
>
> here is my code:
> *
>
> -module(servidor) .
> -behavior(gen_server) .
>
> % API functions
> -export([start_link/0, hi/0, login/2, logout/1, times/2, stop/0]).
>
> % Callback functions
> -export([init/1, handle_call/3, handle_info/2, terminate/2, handle_cast/2,
> code_change/3]).
>
> -define(NAME_SERVER, ?MODULE).
> -define(LOGUEADOS, logeados).
>
>
> start_link() ->
> gen_server:start_link({local, ?NAME_SERVER}, ?MODULE, [], []).%Se registra
> el proceso con el nombre del modulo(servidor)
>
> hi() ->
> gen_server:cast(?MODULE, hi) .
>
> stop() ->
> gen_server:cast(?MODULE, stop).
>
> login(Nick,Pid) ->
> gen_server:call(?MODULE, {login, Nick, Pid}).
>
> logout(Nick) ->
> gen_server:call(?MODULE, {logout, Nick}).
>
> times(N, M) ->
> ?MODULE ! {times_request, self(), {N, M}}.
>
>
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Callback functions implementation %%
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> init([]) ->
> {ok, ets:new(?LOGUEADOS, [set])}.
>
> terminate(_Reason, _State) ->
> {_, Tab} = _State,
> ets:delete(Tab),
> ok.
>
>
> handle_call({login, Nick, Pid}, _From, _State) ->
> %% En el login habra que crear una nodo del que haga el login // Para
> probarlo, miro simplemente si existe en la BD.
> io:format("Loggin.. y state=~w: ~n", [_State]),
> BOOL = ets:member(_State, Nick),
> io:format("The user is online? = ~w ~n", [BOOL]),
> if
> BOOL == true -> io:format("~w its already login", [Nick]);
> true -> ets:insert(_State, {Nick,Pid}), io:format("Login succesful ~n")
> end,
> {reply, {login, Nick}, _State};
>
>
> handle_call({logout, Nick}, _From, _State) ->
> io:format("Logout...~n", []),
> ets:delete(_State, Nick).
>
>
> handle_cast(hi, State) ->
> io:fwrite("\t\tHi!\~n"),
> {noreply, State} ;
>
> handle_cast(stop, _State) ->
> io:format("Stopped~n", []),
> {_, Tab} = _State,
> ets:delete(Tab),
> {stop, normal, _State} .
>
>
> handle_info({times_request, Pid, {N, M}}, State) ->
> io:fwrite("\t~w server handling info, request number ~w~n", [?MODULE,
> State]),
> Pid ! {times_response, N*M},
> {noreply, State} .
>
> code_change(_OldVsn, _State, _Extra) ->
> {ok, _State}.
>
>
> *and then i typed this in one console:*
>
> >erl -sname server
> (server)1> c(servidor).
> {ok,servidor}
> (server)2> servidor:start_link().
> {ok,<0.45.0>}
> (server)3>      
>
>
> *and then i typed this in another console:*
> user)25> {servidor,server} ! {servidor,login,irene,777}.        
> {servidor,login,irene,777}
> (user)26> {servidor,server} ! {servidor,login,irene,777}.
> {servidor,login,irene,777}
> (user)27> {servidor,server} !
> servidor:call(login,irene,6666).
> ** exception error: undefined function servidor:call/3
> (user)28> {servidor,server} ! servidor:login(irene,6666).        
> ** exception exit: {noproc,{gen_server,call,[servidor,{login,irene,6666}]}}
>      in function  gen_server:call/2
> (user)29> {servidor,server} !
> process_request(login,{irene,2321}).
> ** exception error: undefined shell command process_request/2
> (user)30> {servidor,server} ! {hi}.                              
> {hi}
> (user)31> {servidor,server} ! {async,hi}.
>
>
> *almost or the most of instructions makes server_node crash :(*
>
> My question is, what im doing wrong? It is the correct way?
>
>
> --
> View this message in context: http://erlang.2086793.n4.nabble.com/Help-with-gen-server-and-a-chat-server-tp4550462p4550462.html
> Sent from the Erlang Questions mailing list archive at Nabble.com.
> _______________________________________________
> erlang-questions mailing list
> erlang-questions
> http://erlang.org/mailman/listinfo/erlang-questions



Loading...