我有以下简单的UDP服务器:
现在,我的对等UDP客户端将故意发送格式错误的数据。
我可以写一个case子句来匹配任何消息,而忽略任何格式错误的消息。
然而,如果有最终的错误,它不会对我有帮助。
我在某个地方读到:“不要防御性地编程,让它崩溃,然后修复它”。
=ERROR REPORT==== 19-Jul-2020::21:15:29.872000 ===
Error in process <0.93.0> with exit value:
{{case_clause,<<0>>},[{server,loop,1,[{file,"server.erl"},{line,16}]}]}酷,它崩溃了,但我希望我的服务器现在自动重新启动:-)
我已经读到,一个名为“主管”的进程可以监视我的服务器,并在检测到它死后重新启动它。
所以,我使用了"rebar3“,因为它帮助我编译了几个文件,只有一行'rebar3编译‘。
它会用3个文件自动创建一个/src/,但目前只有两个是有趣的:
此外,我已经阅读了这些文档,但我仍然很难理解。
有谁能给我建议,或者将我的19行代码server_app.erl server.erl转换为server.erl,并由一个server_sup.erl来监督?
注:我不是在找gen_server,我经常看到它,但是我也有义务把它转换成gen_server,还是只有application+supervisor可以满足我的需求?
提前谢谢你,
诚挚的问候,
发布于 2020-07-19 22:07:24
监事是OTP 监督树的一部分,它处理所有重新启动策略等等。虽然可以不对其模块使用服务器,但我反对它: gen_servers为最常见的服务器操作提供了一个方便的抽象(并且它们可以直接处理名称注册、系统消息和其他好处)。
尽管“让它崩溃”的引理在Erlang中很常见,但这并不意味着您不必预见代码可能面临的问题,也不意味着您只关心愉快的情况。我不想看到任何系统因为某人的畸形/恶意nc -u而崩溃。
请记住,如果达到了监控程序的重新启动限制,它也将死掉,最终到达应用程序的最高监控器,这会在VM死后崩溃。
让我们来看一下代码(很少编辑rebar3 new app生成的内容):
应用程序不需要任何版本:
-module(server_app).
-behaviour(application).
-export([start/2, stop/1]).
start(_StartType, _StartArgs) ->
server_sup:start_link().
stop(_State) ->
ok.主管有更多的配置,但仅此而已:
-module(server_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
start_link() ->
supervisor:start_link(?MODULE, []).
init([]) ->
SupFlags = #{strategy => one_for_all,
intensity => 0,
period => 1},
ChildSpecs = [#{id => my_server,
start => {server, start_link, [12345]},
type => worker
}],
{ok, {SupFlags, ChildSpecs}}.server.erl需要对start函数进行一些修改:
-module(server).
-export([start_link/1]).
start_link(Port) ->
{ok, spawn_link(fun()->run_it(Port) end)}.
run_it(Port) ->
{ok, Skt} = gen_udp:open(Port, [binary]),
loop(Skt).
loop(Skt) ->
receive
{udp, Skt, _, _, Bin} ->
case Bin of
<<0:32>> ->
io:fwrite("~p~n", [{"Good Format: ", Bin}]),
loop(Skt)
endserver.erl as gen_server应该是这样的:
-module(server).
-export([start_link/1]).
-behaviour(gen_server).
-export([
init/1,
handle_cast/2,
handle_call/3,
handle_info/2
]).
start_link(Port) ->
gen_server:start_link(?MODULE, Port, []).
init(Port) ->
gen_udp:open(Port, [binary]).
handle_call(_Call, _From, State) ->
{reply, ok, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({udp, Skt, _, _, Bin}, Skt) ->
case Bin of
<<0:32>> -> io:fwrite("~p~n", [{"Good Format: ", Bin}])
end,
{noreply, Skt};
handle_info(_Msg, State) -> % Messages that are not {udp, Skt, _, _, _} are discarded
{noreply, State}.https://stackoverflow.com/questions/62984561
复制相似问题