lecture 06

This commit is contained in:
SowinskiBraeden committed 2026-10-20 10:10:30 -07:00
1 parent 8777cee0d0
commit d729786437
28 files changed
+825

No files matched your search

+144
View File
@@ -0,0 +1,144 @@
defmodule Echo.Active do
def start(port \\ 6666) do
opts = [:binary, active: true, packet: :line, reuseaddr: true]
{:ok, listen} = :gen_tcp.listen(port, opts)
accept(listen)
end
def accept(listen) do
{:ok, socket} = :gen_tcp.accept(listen) # data delivered as messages in the mailbox of the
# process that calls accept
spawn(fn -> accept(listen) end)
loop(socket)
end
defp loop(socket) do
receive do
{:tcp, ^socket, data} ->
:gen_tcp.send(socket, data)
loop(socket)
{:tcp_closed, ^socket} ->
:gen_tcp.close(socket)
{:tcp_error, ^socket, _reason} ->
:gen_tcp.close(socket)
end
end
end
defmodule Echo.Passive do
def start(port \\ 6666) do
opts = [:binary, active: false, packet: :line, reuseaddr: true] # note: active: false
{:ok, listen} = :gen_tcp.listen(port, opts)
accept(listen)
end
def accept(listen) do
{:ok, socket} = :gen_tcp.accept(listen) # data delivered as messages in the mailbox of the
# process that calls accept
spawn(fn -> accept(listen) end)
loop(socket)
end
def loop(socket) do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
:gen_tcp.send(socket, data)
loop(socket)
{:error, _reason} ->
:gen_tcp.close(socket)
end
end
end
defmodule Echo.Hybrid do
def start(port \\ 6666) do
opts = [:binary, active: :once, packet: :line, reuseaddr: true]
{:ok, listen} = :gen_tcp.listen(port, opts)
accept(listen)
end
def accept(listen) do
{:ok, socket} = :gen_tcp.accept(listen) # data delivered as messages in the mailbox of the
# process that calls accept (the controlling process)
spawn(fn -> accept(listen) end)
loop(socket)
end
defp loop(socket) do
receive do
{:tcp, ^socket, data} ->
:inet.setopts(socket, active: :once)
:gen_tcp.send(socket, data)
loop(socket)
{:tcp_closed, ^socket} ->
:gen_tcp.close(socket)
{:tcp_error, ^socket, _reason} ->
:gen_tcp.close(socket)
end
end
end
defmodule Echo do
use GenServer
require Logger
def start(port \\ 6666) do
GenServer.start(__MODULE__, port)
end
@impl true
def init(port) do
opts = [:binary, active: true, packet: :line, reuseaddr: true]
{:ok, listen} = :gen_tcp.listen(port, opts)
send(self(), :accept)
{:ok, listen}
end
@impl true
def handle_info(:accept, listen) do
{:ok, socket} = :gen_tcp.accept(listen)
log(socket, "accepted connection")
{:ok, pid} = Echo.Worker.start(socket)
:gen_tcp.controlling_process(socket, pid)
send(self(), :accept)
{:noreply, listen}
end
defp log(socket, msg) do
Logger.info("#{inspect self()}: #{msg} #{inspect socket}")
end
end
defmodule Echo.Worker do
use GenServer
require Logger
def start(socket) do
GenServer.start(__MODULE__, socket)
end
@impl true
def init(socket) do
log(socket, "started worker")
{:ok, socket}
end
@impl true
def handle_info({:tcp, socket, data}, socket) do
:inet.setopts(socket, active: :once)
:gen_tcp.send(socket, data)
{:noreply, socket}
end
@impl true
def handle_info({:tcp_closed, socket}, socket) do
:gen_tcp.close(socket)
log(socket, "closed connection")
{:stop, :normal, socket}
end
defp log(socket, msg) do
Logger.info("#{inspect self()}: #{msg} #{inspect socket}")
end
end