Networking
Packet options: raw/0, 1/2/4 (length-prefixed framing), line, http, http_bin.
34.1 TCP server with gen_tcp
-module(echo_server).
-export([start/1]).
start(Port) ->
{ok, Listen} = gen_tcp:listen(Port, [binary, {packet, line}, {active, false}, {reuseaddr, true}]),
io:format("Listening on ~p~n", [Port]),
accept(Listen).
accept(Listen) ->
{ok, Socket} = gen_tcp:accept(Listen),
Pid = spawn(fun() -> loop(Socket) end),
ok = gen_tcp:controlling_process(Socket, Pid),
accept(Listen).
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} -> gen_tcp:send(Socket, Data), loop(Socket);
{error, closed} -> ok
end.34.2 TCP client
{ok, S} = gen_tcp:connect("localhost", 8080, [binary, {active, false}]),
ok = gen_tcp:send(S, <<"hello\n">>),
{ok, Reply} = gen_tcp:recv(S, 0, 5000),
gen_tcp:close(S).34.3 Active vs passive sockets
{active, false} passive: call recv/2 — natural back-pressure {active, true} data arrives as {tcp, Socket, Data} messages — no flow control {active, once} / {active, N} one/N messages then passive — best of both
Packet options: raw/0, 1/2/4 (length-prefixed framing), line, http, http_bin.
34.4 UDP
{ok, S} = gen_udp:open(9000, [binary, {active, true}]),
gen_udp:send(S, {127, 0, 0, 1}, 9001, <<"ping">>),
receive {udp, S, IP, Port, Data} -> {IP, Port, Data} end.34.5 The socket module (OTP 22+)
Low-level, BSD-socket-like NIF API; also usable as a backend for gen_tcp ({inet_backend, socket}).
{ok, S} = socket:open(inet, stream, tcp),
ok = socket:connect(S, #{family => inet, addr => loopback, port => 8080}),
socket:send(S, <<"hi">>).34.6 SSL/TLS
ssl:start(),
{ok, S} = ssl:connect("example.com", 443, [{verify, verify_peer},
{cacerts, public_key:cacerts_get()},
{server_name_indication, "example.com"}]),
ssl:send(S, <<"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n">>),
{ok, Listen} = ssl:listen(8443, [{certfile, "cert.pem"}, {keyfile, "key.pem"}]).34.7 Production socket acceptor pools
Ranch (used by Cowboy, RabbitMQ) — handles acceptor pools, connection limits, and protocols.