basic TCP echo server with rebar, reltool, ranch and lager
create project skeleton:
mkdir eco cd eco wget https://github.com/rebar/rebar/wiki/rebar chmod u+x rebar ./rebar create-app appid=eco
let's add some dependencies, ranch to accept tcp connections and lager for logging, for that open rebar.config with your text editor and enter this:
{deps, [
{lager, "2.1.0", {git, "https://github.com/basho/lager", {tag, "2.1.0"}}},
{ranch, "1.1.0", {git, "https://github.com/ninenines/ranch", {tag, "1.1.0"}}}
]}.
{erl_opts, [debug_info, {parse_transform, lager_transform}]}.
now let's try compiling it:
./rebar get-deps ./rebar compile
we can start our app from the shell, which won't be really useful, but why not:
erl -pa ebin/ deps/*/ebin
and we run:
1> application:start(eco). ok
now let's use ranch and lager for something, first we create a protocol implementation, open a file called eco_protocol.erl and put the following content in it:
-module(eco_protocol). -behaviour(ranch_protocol). -export([start_link/4]). -export([init/4]). start_link(Ref, Socket, Transport, Opts) -> Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), {ok, Pid}. init(Ref, Socket, Transport, _Opts = []) -> ok = ranch:accept_ack(Ref), loop(Socket, Transport). loop(Socket, Transport) -> case Transport:recv(Socket, 0, 5000) of {ok, Data} -> lager:info("echoing ~p", [Data]), Transport:send(Socket, Data), loop(Socket, Transport); _ -> ok = Transport:close(Socket) end.
edit the start function in src/eco_app.erl so it looks like this:
start(_StartType, _StartArgs) -> {ok, _} = ranch:start_listener(eco, 1, ranch_tcp, [{port, 1883}], eco_protocol, []), eco_sup:start_link().
and add the apps we need in eco.app.src by adding ranch and lager to the applications entry like this:
now let's compile and try again:
./rebar compile
Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.3 (abort with ^G)
1> application:start(eco).
{error,{not_started,ranch}}
2> application:start(ranch).
ok
3> application:start(eco).
{error,{not_started,lager}}
4> application:start(lager).
{error,{not_started,goldrush}}
5> application:start(goldrush).
{error,{not_started,syntax_tools}}
6> application:start(syntax_tools).
ok
7> application:start(goldrush).
{error,{not_started,compiler}}
8> application:start(compiler).
ok
9> application:start(goldrush).
ok
10> application:start(lager).
ok
11> 21:05:52.373 [info] Application lager started on node nonode@nohost
11> application:start(eco).
ok
21:06:09.335 [info] Application eco started on node nonode@nohost
now let's send some data:
telnet localhost 1883 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. asd asd
(I wrote the first asd, the second is the reply)
in the console you should see this log line:
21:10:05.098 [info] echoing <<"asd\r\n">>
now let's build a release so others can use our server (?):
mkdir rel cd rel ../rebar create-node nodeid=eco
add the following two lines to rebar.config:
{sub_dirs, ["rel"]}.
{lib_dirs, ["deps"]}.
and edit rel/reltool.config, change the lib_dirs entry to this:
{lib_dirs, ["../deps"]},
add ranch and lager in the rel entry:
{rel, "eco", "1",
[
kernel,
stdlib,
sasl,
ranch,
lager,
eco
]},
and change the app, echo entry to look like this:
{app, eco, [{mod_cond, app}, {incl_cond, include}, {lib_dir, ".."}]}
now let's try to build a release:
./rebar compile ./rebar generate
now let's start our server:
./rel/eco/bin/eco console
you should see some output like this:
Erlang/OTP 17 [erts-6.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] =INFO REPORT==== 5-Feb-2015::22:15:22 === inet_parse:"/etc/resolv.conf":4: erroneous line, SKIPPED 21:15:22.393 [info] Application lager started on node 'eco@127.0.0.1' 21:15:22.394 [info] Application eco started on node 'eco@127.0.0.1' Eshell V6.3 (abort with ^G) (eco@127.0.0.1)1>
now let's telnet again:
telnet localhost 1883 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. lala! lala!
on the console again you should see some log like this:
21:16:01.540 [info] echoing <<"lala!\r\n">>
and that's it, now evolve your echo server into an actual server :)