Сложность внедрения архитектуры gen_server в erlang

Я относительно новичок в erlang и написал следующие модули:

-module(gserver).
-export([start1/0]).
-define(SERVER, gserver).

 start1() ->
 serv_util:start(?SERVER, 
                  { gserver, game_loop, 
                    [dict:new(), dict:new()]}).

serv_util:

-module(serv_util).
-export([start/2]).

 start(ServerName, {Module, Function, Args}) ->
 global:trans({ServerName, ServerName},
            fun() ->
                case global:whereis_name(ServerName) of
                    undefined ->        
                        Pid = spawn(Module, Function, Args),
                        global:register_name(ServerName, Pid);
                _ ->
                    ok
                end
            end).

Затем я попытался привести его в архитектуру gen_server erlang, как показано ниже:

-module(s_child).
-behaviour(gen_server).

 -export([start/0,stop/0]).
 -export([init/1, handle_call/3,handle_cast/2, terminate/2, 
  handle_info/2,code_change/3]).


 -import(gserver,[start1/0]).
 -import(gclient,[login/1]).



  start()->
  gserver:start1(),
  gen_server:start_link({global,?MODULE}, ?MODULE, [], []).

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

  log_in(Name)->
  gen_server:call({global,?MODULE}, {login,Name,self()}).

  init(_Args) ->
   io:format("Hello started ~n"),
   {ok,_Args}.

   handle_call({login,Name},_From,State)->
   State,
   Reply=login(Name),
   {reply, Reply,State}.

Но когда я вызываю это в следующем порядке

1)s_sup:start_link().

Здравствуйте, запустил {ok,‹0.344.0>}

2) s_child:log_in("Абхишек").

** exception exit: {{function_clause,
                        [{s_child,handle_call,
                             [{login,"Abhishek",<0.335.0>},
                              {<0.335.0>,#Ref<0.0.4.457>},
                              []],
                             [{file,"s_child.erl"},{line,61}]},
                         {gen_server,try_handle_call,4,
                             [{file,"gen_server.erl"},{line,615}]},
                         {gen_server,handle_msg,5,
                             [{file,"gen_server.erl"},{line,647}]},
                         {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,247}]}]},
                    {gen_server,call,
                        [{global,s_child},{login,"Abhishek",<0.335.0>}]}}
     in function  gen_server:call/2 (gen_server.erl, line 204)

И я не могу понять, что именно не так в строке 61 моего кода. В полном коде в строке 61 присутствует следующий код:

handle_call(stop,  _From, State) ->

{stop, normal, ok, State};

то есть первый handle_call присутствует в строке 61

Может ли кто-нибудь помочь мне здесь, пожалуйста.


person abhishek ranjan    schedule 13.07.2017    source источник


Ответы (2)


В функции log_in вы передаете {login,Name,self()} в качестве вызова gen_server, но функция handle_call ожидает только {login,Name}. Таким образом, поскольку нет подходящего предложения, вызов handle_call завершается ошибкой.

Вам не нужно передавать self(), так как вы используете функцию reply, чтобы убедиться, что ответ возвращается вызывающему абоненту, поэтому просто измените log_in, чтобы передать {login,Name} в gen_server:call.

person legoscia    schedule 13.07.2017

Ответ Legoscia правильный.
Я рекомендую ознакомиться с Понимание gen_server.
Эта статья дает полезную информацию для работы с gen_server.

person Pouriya    schedule 13.07.2017
comment
да, я обязательно посмотрю на полезную ссылку, предоставленную вами @Pouriya. Полностью согласен с вами, что мне нужно лучше понять gen_server. Спасибо. - person abhishek ranjan; 13.07.2017