Erlang学习:A non-OTP supervisor for a non-OTP server

本文介绍了一个不使用Erlang OTP框架的简单服务器实现,并通过一个非OTP监督进程来实现进程重启和基本的故障恢复。文章通过具体代码示例展示了如何创建服务器模块、启动及停止服务器、获取服务器状态计数等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:http://blog.bot.co.za/en/article/349/an-erlang-otp-tutorial-for-beginners#.UpoXamSOGJY

A non OTP server:

%%%---------------------------------------------------------------------------
%%% @doc A simple server that does not use OTP.
%%% @author Hans Christian v. Stockhausen <hc at vst.io>
%%% @end
%%%---------------------------------------------------------------------------
 
-module(no_otp).                     % module name (same as our erl filename,
                                     % i.e. no_otp.erl)
 
%% API
-export([                            % the functions we export - our API
  start/0,                           % - start new server process
  stop/0,                            % - stop server
  say_hello/0,                       % - print "Hello" to stdout
  get_count/0                        % - reply with number of times the main 
  ]).                                %   loop was executed
 
%% Callbacks
-export([init/0]).                   % exported so we can spawn it in start/0
                                     % listed as a separate export here as a
                                     % hint to clients not to use it
 
-define(SERVER, ?MODULE).            % SERVER macro is an alias for MODULE,
                                     % and expands to 'no_otp'
 
-record(state, {count}).             % record for our server state. Rather
                                     % arbitrarily we track how often the
                                     % main loop is run - see loop/1
 
 
%=============================================================================
% API - functions that our clients use to interact with the server
%=============================================================================
 
start() ->                           % spawn new process that calls init/0  
  spawn(?MODULE, init, []).          % the new process' PID is returned
 
stop() ->                            % send the atom stop to the process                           
  ?SERVER ! stop,                    % to instruct our server to shut down
  ok.                                % and return ok to caller
 
say_hello() ->                       % send the atom say_hello to the process
  ?SERVER ! say_hello,               % to print "Hello" to sdout
  ok.
 
get_count() ->                       % send callers Pid and the atom get_count
  ?SERVER ! {self(), get_count},     % to request counter value
  receive                            % wait for matching response and return
    {count, Value} -> Value          % Value to the caller
  end. 
 
 
%=============================================================================
% callback functions - not to be used by clients directly
%=============================================================================
 
init() ->                            % invoked by start/0
  register(?SERVER, self()),         % register new process PID under no_otp
  loop(#state{count=0}).             % start main server loop
 
%=============================================================================
% internal functions - note, these functions are not exported
%=============================================================================
 
loop(#state{count=Count}) ->         % the main server loop
  receive Msg ->                     % when API functions send a message
    case Msg of                      % check the atom contained
      stop ->                        % if atom is 'stop'
        exit(normal);                %   exit the process
      say_hello ->                   % if atom is 'say_hello'
        io:format("Hello~n");        %   write "Hello" to stdout
      {From, get_count} ->           % if Msg is tuple {Pid(), get_count}
        From ! {count, Count}        % reply with current counter value
    end                              %   in tagged tupple {count, Value}
  end,
  loop(#state{count = Count + 1}).   % recurse with updated state

A non-OTP supervisor

%%%----------------------------------------------------------------------------
%%% @doc A non-OTP supervisor
%%% @author Hans Christian v. Stockhausen <hc at vst.io>
%%% @end
%%%----------------------------------------------------------------------------

-module(sup).

%% API
-export([start_server/0]).

%% Callbacks
-export([supervise/0]).

%%=============================================================================
%% API
%%=============================================================================

start_server() ->
  spawn(?MODULE, supervise, []).

%%=============================================================================
%% Callbacks
%%=============================================================================

supervise() ->
  process_flag(trap_exit, true),    % don't crash us but rather send us a
                                    %  message when a linked process dies
  Pid = no_otp:start(),             % start our server
  link(Pid),                        % and link to it
  receive {'EXIT', Pid, Reason} ->  % wait for a message that informs us
    case Reason of                  %  that our porcess shut down
      normal -> ok;                 % if the reason is 'normal' do nothing
      _Other -> start_server()      %  otherwise start all over 
   end
  end.

运行:

Eshell V5.8.5  (abort with ^G)
1> c(sup).                                   % compile our supervisor module
{ok,sup}
2> sup:start_server().                       % start the supervisor
<0.39.0>                                     % it got the process ID ..39..
3> whereis(no_otp).                          % let's find our no_otp process
<0.40.0>                                     % it got ..40..
4> no_otp:say_hello().                       % let's try to use the API
Hello                                        % works
ok
5> no_otp:get_count().                       % works too 
1
6> no_otp ! crash.                           % time to crash it
crash

=ERROR REPORT===
Error in process <0.40.0> with exit value: 
  {{case_clause,crash},[{no_otp,loop,1}]}   % as expected a case_clause error

7> no_otp:get_count().                      % but a new process was started
0                                           % as we can see here
8> no_otp:stop().                           % now let's stop it 'normally'
ok
9> whereis(no_otp).                         % and check for a new instance
undefined                                   % but there is none. Correct!
10>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值