Joe Williams home
The last few days I have been playing with gen_tcp and writing a simple TCP server. I have found a number of resources helpful: gen_tcp, miniserv, 20bits and Programming Erlang. My server will run and display the data sent to it along with the client IP address and a timestamp. The server will also echo back whatever the client sent. It uses {active, once} for flow control as well. I just used telnet as my client. Pretty simple but a good exercise to see how this stuff works. erl_tcp.erl
-module(erl_tcp). -export([start_server/0, connect/1, recv_loop/1]). -define(LISTEN_PORT, 9000). -define(TCP_OPTS, [binary, {packet, raw}, {nodelay, true}, {reuseaddr, true}, {active, once}]). start_server() -> % start up the service and error out if we cannot case gen_tcp:listen(?LISTEN_PORT, ?TCP_OPTS) of {ok, Listen} -> spawn(?MODULE, connect, [Listen]), io:format("~p Server Started.~n", [erlang:localtime()]); Error -> io:format("Error: ~p~n", [Error]) end. connect(Listen) -> {ok, Socket} = gen_tcp:accept(Listen), inet:setopts(Socket, ?TCP_OPTS), % kick off another process to handle connections concurrently spawn(fun() -> connect(Listen) end), recv_loop(Socket), gen_tcp:close(Socket). recv_loop(Socket) -> % reset the socket for flow control inet:setopts(Socket, [{active, once}]), receive % do something with the data you receive {tcp, Socket, Data} -> io:format("~p ~p ~p~n", [inet:peername(Socket), erlang:localtime(), Data]), gen_tcp:send(Socket, "I Received " ++ Data), recv_loop(Socket); % exit loop if the client disconnects {tcp_closed, Socket} -> io:format("~p Client Disconnected.~n", [erlang:localtime()]) end.
Hopefully all of that made some sense. Here is an example of usage, first starting the server and receiving a message.
[zeusfaber@der-dieb ebin]$ erl Erlang (BEAM) emulator version 5.6.5 [source] [64-bit] [smp:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> erl_tcp:start_server().
To send the message "TEST123" I simply used telnet. Of course you could also write a client in Erlang to do the same.
[zeusfaber@der-dieb ~]$ telnet localhost 9000 Trying Connected to localhost. Escape character is '^]'. TEST123 I Received TEST123
Fork me on GitHub