一人 Erlang 勉強会をやればいいのか?

TCP Echo Server/Client はいくらでもあるので、
UDP Echo Server/Client を書いてみました。

並列化がまだ理解してない上、並列時のエラー処理も理解していません。
書きにくいとは思わないのですが、うまく書く方法がまだわかりません ... 。

%% vim: sw=4 sts=4

-module(udp_test).
%% -compile(export_all).
-export([start_echo_server/0, echo_client/1]).
-define(PORT, 1234).

start_echo_server() ->
    _ = spawn(fun() -> echo_server(?PORT) end).

echo_server(Port) ->
    case gen_udp:open(Port, [binary]) of
        {ok, Socket} ->
            loop(Socket);
        {error, Reason} ->
            io:format("~p ~p~n", [Port, Reason])
    end.

loop(Socket) ->
    receive
        {udp, Socket, IP, Port, Packet} ->
            _ = spawn(fun() -> server_send_udp(Socket, IP, Port, Packet) end),
            loop(Socket)
    end.

server_send_udp(Socket, Address, Port, Packet) ->
    ok = gen_udp:send(Socket, Address, Port, Packet),
    io:format("~p ~p~n", [Port, Packet]).

echo_client(String) ->
    case gen_udp:open(0, [binary]) of
        {ok, Socket} ->
            _ = spawn(fun() -> client_send_udp(Socket, list_to_binary(String)) end);
        {error, Reason} ->
            io:format("~p ~p~n", [?PORT, Reason])
    end.

client_send_udp(Socket, Binary) ->
    case gen_udp:send(Socket, "127.0.0.1", ?PORT, Binary) of
        ok ->
            io:format("~p~n", [binary_to_list(Binary)]);
        {error, Reason} ->
            io:format("~p ~p~n", [?PORT, Reason]),
            gen_udp:close(Socket)
    end,

    receive
        {udp, Socket, _, _, Packet} ->
            io:format("~p", binary_to_list(Packet)),
            gen_udp:close(Socket)
    after 2000 ->
        gen_udp:close(Socket)
    end.