如何接收发送到 gen_server 内 运行 的 PID 的消息
How can I receive messages sent to a PID which running inside a gen_server
我有一个 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) 说:
If network goes down or something unexpected happens the gun
connection with APNs will go down. In that case apns4erl will send a
message {reconnecting, ServerPid}
to the client process, that means
apns4erl lost the connection and it is trying to reconnect. Once the
connection has been recover a {connection_up, ServerPid}
message will
be send.
我的问题是:
- 我应该在
my_apns_module.erl
里面写什么代码来接收{reconnecting, ServerPid}
或{connection_up, ServerPid}
?
发送到 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进程会进入循环等待消息
我有一个 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) 说:
If network goes down or something unexpected happens the gun connection with APNs will go down. In that case apns4erl will send a message
{reconnecting, ServerPid}
to the client process, that means apns4erl lost the connection and it is trying to reconnect. Once the connection has been recover a{connection_up, ServerPid}
message will be send.
我的问题是:
- 我应该在
my_apns_module.erl
里面写什么代码来接收{reconnecting, ServerPid}
或{connection_up, ServerPid}
?
发送到 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进程会进入循环等待消息