[erlang] ranch 服务器搭建

前言

正常情况下, 当我们需要连接外部资源的时候, 有两种方法, 一种是 http 请求的方法, 另一种则是 socket 请求的方法. http 请求对应的是 cowboy, 而 socket 请求对应的则是 ranch. socket 请求比较常见的是传输银行规则里的 8583 报文.

创建项目

  1. 使用 rebar3 new release 的方法创建一个新的 otp 项目.
  2. 在 .app 文件启动 ranch 监听
{ok, _Pid} = ranch:start_listener(service_tcp, Acceptor, ranch_tcp,
        [
          {port, Port},
          {max_connections, Max_connect}
        ],
        service_tcp_protocol, []);

上面代码中, service_tcp 是连接的名称, Acceptor 代表接收器的数量, port代表向外开放的端口, service_tcp_protocol 代表处理模块的名字. 另外, 可以将 Acceptor 放到列表中, 格式为 {num_acceptors, Acceptor}, 这两种写法ranch都支持.

  1. 如果要使用 ssl 格式而非 tcp 格式, 则需要几个额外参数,
          {certfile, CertFile},
          {cacertfile, CaCertFile},
          {keyfile, KeyFile}

以上参数的获取方式可以参考 https://ninenines.eu/docs/en/ranch/1.7/guide/ssl_auth/

  1. 处理模块可以使用 gen_server 的模式.
start_link(Ref, Socket, Transport, Opts) ->
  proc_lib:start_link(?MODULE, init, [Ref, Socket, Transport, Opts]).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) ->
  process_flag(trap_exit, true),
  {ok, undefined}.

init(Ref, Socket, Transport, _Opts = []) ->
  ok = proc_lib:init_ack({ok, self()}),
  ok = ranch:accept_ack(Ref),
  ok = Transport:setopts(Socket, [{active, once}, {packet, 0}]),
  gen_server:enter_loop(?MODULE, [], #state{socket = Socket, transport = Transport}, TIMEOUT).

handle_call(_Request, _From, State) ->
  {reply, ok, State}.

handle_cast(_Request, State) ->
  {noreply, State}.

handle_info({tcp, Socket, Data}, State = #state{socket = Socket, transport = TransPort}) ->
  Response = Data,
  TransPort:setopts(Socket, [{active, once}]),
  TransPort:send(Socket, Response),
  {noreply, State, 0};
handle_info({tcp_closed, _Socket}, State) ->
  {stop, normal, State};
handle_info({tcp_error, _, Reason}, State) ->
  {stop, Reason, State};
handle_info(timeout, State) ->
  {stop, normal, State};
handle_info(Info, State) ->
  {stop, normal, State}.

terminate(_Reason, _State) ->
  ok.

code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

你可能感兴趣的:([erlang] ranch 服务器搭建)