首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >rebar3,主管,行为(申请)

rebar3,主管,行为(申请)
EN

Stack Overflow用户
提问于 2020-07-19 19:10:35
回答 1查看 125关注 0票数 0

我有以下简单的UDP服务器:

  • 只接受二进制<<0:32>>,
  • 否则它就崩溃了 -module(服务器)。-export(听/1)。听(端口) ->派生(fun()->run_it(端口)结束)。Run_it(端口) -> {ok,Skt} =gen_udp:open(端口,二进制),循环(Skt)。循环( Skt ) ->接收{udp、Skt、_、_、-> } case的<<0:32>> -> io:fwrite("~p~n",{"Good Format:",Bin}),_(Skt)结束。

现在,我的对等UDP客户端将故意发送格式错误的数据。

我可以写一个case子句来匹配任何消息,而忽略任何格式错误的消息。

然而,如果有最终的错误,它不会对我有帮助。

我在某个地方读到:“不要防御性地编程,让它崩溃,然后修复它”。

代码语言:javascript
复制
    =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/,但目前只有两个是有趣的:

  • server_app.erl
  • server_sup.erl

此外,我已经阅读了这些文档,但我仍然很难理解。

有谁能给我建议,或者将我的19行代码server_app.erl server.erl转换为server.erl,并由一个server_sup.erl来监督?

注:我不是在找gen_server,我经常看到它,但是我也有义务把它转换成gen_server,还是只有application+supervisor可以满足我的需求?

提前谢谢你,

诚挚的问候,

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-19 22:07:24

监事是OTP 监督树的一部分,它处理所有重新启动策略等等。虽然可以不对其模块使用服务器,但我反对它: gen_servers为最常见的服务器操作提供了一个方便的抽象(并且它们可以直接处理名称注册系统消息和其他好处)。

尽管“让它崩溃”的引理在Erlang中很常见,但这并不意味着您不必预见代码可能面临的问题,也不意味着您只关心愉快的情况。我不想看到任何系统因为某人的畸形/恶意nc -u而崩溃。

请记住,如果达到了监控程序的重新启动限制,它也将死掉,最终到达应用程序的最高监控器,这会在VM死后崩溃。

让我们来看一下代码(很少编辑rebar3 new app生成的内容):

应用程序不需要任何版本:

代码语言:javascript
复制
-module(server_app).

-behaviour(application).
-export([start/2, stop/1]).

start(_StartType, _StartArgs) ->
    server_sup:start_link().

stop(_State) ->
    ok.

主管有更多的配置,但仅此而已:

代码语言:javascript
复制
-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函数进行一些修改:

代码语言:javascript
复制
-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)
            end

server.erl as gen_server应该是这样的:

代码语言:javascript
复制
-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}.
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62984561

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档