This is my implementation of a UDP server (copied below). I haven't noticed any of the problems you mentioned. Hope it helps.
defmodule Transports.Udp.Server do
require Lager
use GenServer
alias Transactions.Server
def start_link(port) do
GenServer.start_link(__MODULE__, port, [])
end
def init(port) do
{:ok, socket} = :gen_udp.open(port, [:binary, {:active, false}])
pid = spawn_link fn -> process_loop(socket) end
:ok = :gen_udp.controlling_process(socket, pid)
{:ok, pid}
end
def stop(state) do
pid = state
send pid, :stop
:ok
end
def handle_info(_msg, state), do: { :noreply, state }
def terminate(_reason, _state), do: :ok
defp process_loop(socket) do
:inet.setopts(socket, [{:active, :once}])
receive do
{:udp, socket, host, port, request} ->
spawn fn ->
ip_address = :inet_parse.ntoa(host) |> List.to_string
Lager.debug("Received from #{ip_address}: #{inspect(request, limit: 1000)}")
{:ok, reply} = Server.process(request, { :udp, ip_address })
:gen_udp.send(socket, host, port, reply )
Lager.debug("Replied to #{ip_address}: #{inspect(reply, limit: 1000)}.")
end
process_loop(socket)
end
end
end