Erlang 如何接收发送到在gen_服务器内运行的PID的消息

Erlang 如何接收发送到在gen_服务器内运行的PID的消息,erlang,ejabberd,erlang-supervisor,ejabberd-module,Erlang,Ejabberd,Erlang Supervisor,Ejabberd Module,我有一台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

我有一台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}.
    
    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]) ->
        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().
      
    
  • 在init内部,我运行另一个APNs应用程序来发送推送通知

  • 这是工作,因为我可以发送通知

  • 现在文档()显示:

  • 如果网络瘫痪或发生意外情况,枪会自动关闭 与APN的连接将断开。在这种情况下,apns4erl将发送一个 消息
    {正在重新连接,ServerPid}
    到客户端进程,这意味着 apns4erl失去连接,正在尝试重新连接。一旦 连接已恢复,将显示一条
    {connection\u up,ServerPid}
    消息 被派去

    我的问题是:

    • 要接收
      {reconnecting,ServerPid}
      {connection\u up,ServerPid}
      ,我应该在
      my_apns_module.erl
      中写入什么代码

    发送到gen_服务器进程的消息,例如
    GenServerPid!{ok,10}
    },由以下人员处理:

    handle_info(Msg, State)
    
    所以,你可以这样做:

    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}.
    
    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]) ->
        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().
      
    
    评论回复:

    这是您当前的代码:

    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}}.
    
    您可以将其更改为以下内容:

    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}.
    
    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]) ->
        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_服务器,比如GenServerPID,而是发送到gen_服务器内部运行的进程,比如PID。该进程是由语句{OK,PID}=apns:connect(cert,?apns\U CONNECTION)启动的。因此GenServerPID由ejabberd启动,PID通过我的apns模块内部的apns:connect启动。据我所知,handle_info将处理ejabberd服务器发送到GenServerPID的消息。它还会处理发送给PID的消息吗?据我所知,handle_info将处理ejabberd服务器发送给GenServerPID的消息。它还会处理发送到PID的消息吗?--发送到非gen_服务器进程的消息需要由receive子句处理。@GJain,我添加了一个您可以做的示例。很抱歉。。。我还有一个问题..spawn将启动一个新进程,比如说spawnPID..但是apns将消息发送给PID,所以(apns_循环处理spawnPID还是PID)或者(spawnPID==PID)?GJain,哪个进程是PID?在这种情况下,apns4erl将向客户端进程发送一条消息{reconnecting,ServerPid}——您必须找出哪个进程是
    客户端进程。