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.
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
endThe 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…