This code let’s me connect with a 2d camera.
I’m running Linux and I can read the messages from the TCP server on the camera.
But it never triggers :tcp_closed or :tcp_error which I’d expect to happen after unplugging the Ethernet cable (rj45).
When I do unplug the cable, the message stop coming in. After reconnecting the cable the messages come in again, without even mentioning the connection was temporarily severed.
defmodule TcpClient do
use GenServer
require Logger
@con_opts [:binary, active: true, packet: :raw, send_timeout: 10000]
@connect_timeout 2000
@retry_interval 1000
defmodule State do
defstruct host: "localhost",
port: 1234
end
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def init(opts) do
state = opts_to_initial_state(opts)
send(self(), :connect)
{:ok, state}
end
def handle_info(:connect, state) do
Logger.info("Connecting to #{state.host}:#{state.port}")
case :gen_tcp.connect(state.host, state.port, @con_opts, @connect_timeout) do
{:ok, _socket} ->
Logger.info("Connected successfully to #{state.host}:#{state.port}")
{:noreply, state}
{:error, reason} ->
Logger.warning(
"Connection to #{state.host}:#{state.port} failed: #{inspect(reason)}. Will retry in #{@retry_interval}ms"
)
{:noreply, state, @retry_interval}
end
end
def handle_info(:timeout, state) do
send(self(), :connect)
{:noreply, state}
end
def handle_info({:tcp_closed, _socket}, state) do
Logger.info("Connection to #{state.host}:#{state.port} closed. Reconnecting...")
send(self(), :connect)
{:noreply, state}
end
def handle_info({:tcp_error, _socket, reason}, state) do
Logger.info("Connection to #{state.host}:#{state.port} error: #{inspect(reason)}")
send(self(), :connect)
{:noreply, state}
end
def handle_info({:tcp, _socket, data}, state) do
string =
Regex.scan(~r/star;(\S+);stop/, data <> data, capture: :all_but_first)
|> List.first()
|> List.first()
Logger.info("String: #{string}")
{:noreply, state}
end
defp opts_to_initial_state(opts) do
host = Keyword.get(opts, :host, "localhost") |> String.to_charlist()
port = Keyword.fetch!(opts, :port)
%State{host: host, port: port}
end
end






















