TCP server with a process per connection

Three lines of substance: :gen_tcp.listen opens the port. accept blocks. spawn(fn -> serve(socket) end) launches one BEAM process per connection. Done.

01-tcp-echo/server.exs
elixir
defmodule EchoServer do
  def start(port) do
    {:ok, listen} = :gen_tcp.listen(port, [:binary, active: false, reuseaddr: true])
    accept_loop(listen)
  end

  defp accept_loop(listen) do
    {:ok, socket} = :gen_tcp.accept(listen)
    pid = spawn(fn -> serve(socket) end)
    :gen_tcp.controlling_process(socket, pid)
    accept_loop(listen)
  end

  defp serve(socket) do
    case :gen_tcp.recv(socket, 0) do
      {:ok, data} -> :gen_tcp.send(socket, data); serve(socket)
      {:error, _} -> :gen_tcp.close(socket)
    end
  end
end

The entire echo server. Process-per-connection is the default OTP shape.

Both are cheap, both isolated. Goroutines (~2 KB) are scheduled by the Go runtime. BEAM processes (~3 KB) are scheduled by the BEAM scheduler with preemption at function calls. The differentiating feature: BEAM processes have isolated heaps. A crash in one process cannot corrupt another. That is why Erlang got the telecom-grade reputation.

Quiz: Quiz

Loading practice…