【问题标题】:Erlang: how to get result from init() in gen_serverErlang:如何从 gen_server 中的 init() 获取结果
【发布时间】:2012-08-29 13:31:55
【问题描述】:

我的 init() 函数创建 UDP Socket 并将 Socket 值作为状态返回。

start() ->
        {ok, ServerPid} = gen_server:start_link(?MODULE, [], []).

%%% gen_server API

init([]) ->
        {ok, Socket} = gen_udp:open(8888, [list, {active,false}]),
        {ok, Socket}.

如何在我的函数 start() 中获取 Socket?

【问题讨论】:

    标签: erlang gen-server


    【解决方案1】:

    您需要通过为新创建的 gen_server 进程创建 gen_server:call 来获取套接字。例如:

    start() ->
            {ok, ServerPid} = gen_server:start_link(?MODULE, [], []),
            Socket = gen_server:call(ServerPid, fetch_socket),
            ... Use Socket ...
    

    并在 gen_server 中添加如下内容:

    handle_call(fetch_socket, _From, State) ->
       {reply, State, State}. %% State == Socket
    

    【讨论】:

      【解决方案2】:

      如果你需要 udp 套接字 int 你的 start 函数,你也可以在 start 函数中创建它,并将它作为参数传递给 start 链接调用。这样您就不必在创建服务器后调用它。

      rvirding 指出这将导致启动进程从 udp 套接字接收消息,而不是新生成的服务器。有关详细信息,请参阅 cmets。从问题中不清楚在 start 方法中究竟需要什么套接字,但请确保这是您想要的行为。

      start() ->
          {ok, Socket} = gen_udp:open(8888, [list, {active,false}]),
          {ok, ServerPid} = gen_server:start_link(?MODULE, Socket, []).
      
      %%% gen_server API
      
      init(Socket) ->
          {ok, Socket}.
      

      【讨论】:

      • 是的,你可以这样做。但是打开套接字的进程默认情况下是控制进程,并且是在活动模式下接收数据包的进程,如果它死了会导致套接字关闭。在这种情况下,这可能不是您想要的!解决方案是使用函数gen_udp:controlling_process 将控制权转移到gen_server。但是,这将打破start/start_link 返回{ok,Pid} 的约定,这是一件坏事。最好查询服务器。
      • 您是对的,您可能确实不希望启动过程成为控制过程,尽管从上下文中不清楚。但是,为什么使用gen_udp:controlling_process 会阻止您返回{ok, Pid}
      • 当然不会阻止您返回{ok,Pid}。我的意思是,在最初的问题中,他想从 start 函数返回 {ok,Socket},而 THIS 会打破惯例。
      猜你喜欢
      • 2019-07-17
      • 2012-06-17
      • 2012-09-05
      • 2011-10-08
      • 2011-08-09
      • 2014-11-09
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      相关资源
      最近更新 更多