【问题标题】:How can I receive messages sent to a PID which running inside a gen_server如何接收发送到在 gen_server 内运行的 PID 的消息
【发布时间】:2021-06-02 11:39:09
【问题描述】:
  • 我有一个 ejabberd 服务器

  • 我有一个自定义模块,my_apns_module.erl,它由 ejabberd 服务器运行,如下所示:

    start_link(Host, Opts) ->
      Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
      ?GEN_SERVER:start_link({local, Proc}, ?MODULE,
                             [Host, Opts], []).
    start(Host, Opts) ->
      Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
      ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
                   temporary, 1000, worker, [?MODULE]},
      supervisor:start_child(ejabberd_sup, ChildSpec).
    
    stop(Host) ->
      Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
      ?GEN_SERVER:call(Proc, stop),
      supervisor:delete_child(ejabberd_sup, Proc),
      ok.
    
    init([Host, _Opts]) ->
       ...
    
    handle_call(stop, _From, State) ->
      {stop, normal, ok, State}.
    
    handle_cast(_Msg, State) -> {noreply, State}.
    
    handle_info(#offline_msg{us = _UserServer,
              from = From, to = To, packet = Packet} = _Msg, State) ->
      ...
    
    handle_info(_Info, State) ->
      {noreply, State}.
    
    terminate(_Reason, State) ->
      Host = State#state.host,
      ok.
    
    code_change(_OldVsn, State, _Extra) -> {ok, State}.
    
  • 在 init 中,我运行另一个 APNs 应用程序来发送推送通知。 https://github.com/inaka/apns4erl

    init([Host, _Opts]) ->
          apns:start(),
          case apns:connect(cert, ?APNS_CONNECTION) of
               {ok, PID} -> ?INFO_MSG("apns connection successful with PID ~p~n", [PID]);
               {error, timeout} -> ?ERROR_MSG("apns connection unsuccessful reason timed out", [])
          end,
          {ok, #state{host = Host}}.
    
  • 这是有效的,因为我可以发送通知。

  • 现在文档 (https://github.com/inaka/apns4erl) 说:

如果网络出现故障或发生意外情况,枪 与 APN 的连接将断开。在这种情况下,apns4erl 将发送一个 向客户端进程发送消息{reconnecting, ServerPid},这意味着 apns4erl 失去了连接,它正在尝试重新连接。一旦 连接已恢复 {connection_up, ServerPid} 消息将 发送。

我的问题是:

  • 我应该在my_apns_module.erl 中写什么代码来接收{reconnecting, ServerPid} 或{connection_up, ServerPid}?

【问题讨论】:

    标签: erlang ejabberd erlang-supervisor ejabberd-module


    【解决方案1】:

    发送到 gen_server 进程的消息,例如GenServerPid ! {ok, 10}},由:

    handle_info(Msg, State)
    

    所以,你可以这样做:

    handle_info({reconnecting, ServerPid}=Msg, State) ->
         %%do something here, like log Msg or change State;
    handl_info({connection_up, ServerPid}=Msg, State) ->
         %%do something here, like log Msg or change State;   
    handle_info(#offline_msg{us = _UserServer,
              from = From, to = To, packet = Packet} = _Msg, State) ->
         %%do something.
    

    对评论的回应:

    这是您当前的代码:

    init([Host, _Opts]) ->
          apns:start(),
          case apns:connect(cert, ?APNS_CONNECTION) of
               {ok, PID} -> ?INFO_MSG("apns connection successful with PID ~p~n", [PID]);
               {error, timeout} -> ?ERROR_MSG("apns connection unsuccessful reason timed out", [])
          end,
          {ok, #state{host = Host}}.
    

    你可以把它改成这样:

    init([Host, _Opts]) ->
        spawn(?MODULE, start_apns, []),
        ...
    
    
    start_apns() ->
    
              apns:start(),
              case apns:connect(cert, ?APNS_CONNECTION) of
                   {ok, PID} -> ?INFO_MSG("apns connection successful with PID ~p~n", [PID]);
                   {error, timeout} -> ?ERROR_MSG("apns connection unsuccessful reason timed out", [])
              end,
              apns_loop().
    
    apns_loop() ->
        receive
            {reconnecting, ServerPid} -> %%do something;
            {connection_up, ServerPid} -> %% do something;
            Other -> %% do something
        end,
        apns_loop().
      
    

    启动apns进程后,apns进程会进入循环等待消息。

    【讨论】:

    • 等一下...消息不会发送到 gen_server,比如说 GenServerPID,而是发送到在 gen_server 中运行的进程,比如说 PID。该过程由语句 {OK, PID} = apns:connect(cert, ?APNS_CONNECTION) 启动。所以 GenServerPID 是由 ejabberd 启动的,而 PID 是通过 my_apns_module 中的 apns:connect 启动的。据我了解,handle_info 将处理 ejabberd 服务器发送到 GenServerPID 的消息。它还会处理发送到 PID 的消息吗?
    • 据我所知,handle_info 将处理 ejabberd 服务器发送到 GenServerPID 的消息。它还会处理发送到 PID 的消息吗?-- 发送到非 gen_server 进程的消息需要由接收子句处理。
    • @GJain,我添加了一个你可以做什么的例子。
    • 对不起......我还有一个问题...... PID)还是(是 spawnPID == PID)?
    • GJain,哪个进程是PID? 在这种情况下,apns4erl 将向客户端进程发送一条消息 {reconnecting, ServerPid} -- 你必须弄清楚哪个进程是client process。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 2017-02-23
    • 1970-01-01
    相关资源
    最近更新 更多