
This week I had to write a little tool that would collect input on
different channels, via socket / netcat, via a http server, .... Calls
for a parralel Design -- Maybe a good place to write something real in
Erlang. While erlang itself was really nice
to write -- I do like Prolog as well as the bunch of functional
languages -- doing networking in erlang seems a bit
special, the
interfaces just aren't thin wrappers around the libc stuff.
Getting a Socket Text interface
What sounds like a easy challenge to accomplish was actually harder
than expected. All I found was some way to pass binaries representing
erlang code over a socket and evaluating it remotle. While it's nice
that such things are as easy to do as they are it doesn't help me with
my task of moving simple strings.
start() ->
ok, Listen = gen_tcp:listen(51622, [binary, packet, 0 ,
reuseaddr, true ,
active, true ]),
spawn(fun () -> accept_loop(Listen) end).
accept_loop(Listen) ->
ok, Socket = gen_tcp:accept(Listen),
accept_loop(Listen),
handle(Socket)
handle(Socket) ->
receive
tcp, Socket, Bin ->
io:format("~p~n", binary_to_list(Bin));
tcp_closed, Socket ->
Buffer
end.
So the socket is now up and receives text as wanted. However, as we
are already runnign a parralel program it would be nice to be hable to
handle multiple socket connections in parralel right? For that we just
need to add a
spawn()
at the right place. The right place is
not
the
handle(Socket)
but the
accept_loop(Listen)
because the process
that called
accept
will receive all the tcp messages.
This last part was quite obvious after finding the documentation of
the
active, _
properties for the socket.
always
here means that
you'll receive all data from the socket as erlang Messages,
once
delivers one package and waits until it is activated again and
false
requires calling a method -- this would have been possible as well
when forking
handle(Socket)
.
The web server
Ok we also want a webserver. We do
not want to run some
webapplication inside appache or so, just do some post/get and simple
pages. Erlang here provides a built-in
httpd
with some
mod_esi
that calls some function depending on the URL used. It doesn't do
anything fancy like templating or DB backends or stuff, just taking
strings and building the http answers.
Unfortunately there are no examples around and basically noone seems
to be using this combination (apart from some hacks like mine
probably). So as I needed to get some additional information into the
handler function (a
Pid
to connect to some service), I, as a novice,
just couldn't find a way. Asking on IRC the solution was rather
simple: Just using erlang's process registry. For more complex stuf
gproc
might prove usefull here.
Result
I guess I've got a huge step farther in programming erlang now. The
manpages are easily found by your search engine -- for python I have
to either walk through the (well structured) online documentation or
search for the right link in the search results, for erlang they're
typically first. Also
Joe Armstrong's Books
as proven usefull. The most dificult part probably is getting around
all the nice extras you can do (transfering functions over sockets et
al) and find out how to do the thing you need.