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 :)