Koszal

Koszal

Protohackers in Elixir - day 0

I followed a tutorial and created a gen_tcp server. The code is shown below. The server accepts connections, receives data but the function recv_until_closed (at the very bottom) never matches on {:error, :closed}. Consequently, the connections are never closed. Instead I eventually get timeout errors. I’m testing it by echoing a string to nc localhost 5001 as shown in the video (around 17:30)

This is the first video in the Photohackers in Elixir series

Is there some obvious error in my code that I’m failing to see?

defmodule EventListener.Server do
  use GenServer
  require Logger

  def start_link([] = _opts) do
    GenServer.start_link(__MODULE__, :no_state)
  end

  defstruct [:listen_socket]

  @impl true
  def init(:no_state) do

    listen_options = [
      ifaddr: {0, 0, 0, 0},
      mode: :binary,
      active: false,
      reuseaddr: true,
      exit_on_close: false
    ]

    case :gen_tcp.listen(5001, listen_options) do
      {:ok, listen_socket} ->

        state = %__MODULE__{listen_socket: listen_socket}
        {:ok, state, {:continue, :accept}}

      {:error, reason} ->
        {:stop, reason}
    end
  end

  @impl true
  def handle_continue(:accept, %__MODULE__{} = state) do
    case :gen_tcp.accept(state.listen_socket) do
      {:ok, socket} ->
        handle_connection(socket)
        {:noreply, state, {:continue, :accept}}
      {:error, reason} ->
        {:stop, reason}
    end
  end

  defp handle_connection(socket) do
    case recv_until_closed(socket, _buffer = "") do
      {:ok, data} -> 
        :gen_tcp.send(socket, data)
      {:error, reason} ->
        Logger.error("Failed to receive data: #{inspect(reason)}");
    end

    :gen_tcp.close(socket)
  end

  defp recv_until_closed(socket, buffer) do
    case :gen_tcp.recv(socket, 0, 10_000) do
      {:ok, data} -> 
        recv_until_closed(socket, [buffer, data])
      {:error, :closed} -> 
        {:ok, buffer} 
      {:error, reason} -> {:error, reason}
    end
  end
end

Most Liked

Koszal

Koszal

I’m testing it by echoing a string to nc localhost 5001 as shown in the video

-N helps. From man nc:

-N
shutdown(2) the network socket after EOF on the input. Some servers require this to finish their work.

Where Next?

Popular in Challenges Top

antoine-duchenet
Everything went smoothly today. Nothing to change to solve part 2 because I already used memoization for part 1 (it looked like an AoC e...
New
Aetherus
This topic is about Day 15 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/l...
New
shritesh
This was way too easy after the last few days. Simple map, filter and count.
New
Aetherus
The second part of today’s puzzle is very misleading. FYI, each of the ghosts has only one possible position that ends with a "Z" on its...
New
Aetherus
This topic is about Day 7 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/le...
New
bjorng
Note: This topic is to talk about Day 1 of the Advent of Code 2019.
New
code-shoily
Just did part 1. Part 2 seems to be demanding too much of my reading time so will get to that after I am done with some chores. Oh here ...
New
New
cblavier
Hi, there :wave: Today, I felt it was way more challenging! I went through part2 thanks to Agent based memoization (without memoization ...
New
Aetherus
I spent 3 hours struggling in part 2, until I noticed a very basic mistake :joy: Here’s my code: By the way, the starting position in...
New

Other popular topics Top

chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New

We're in Beta

About us Mission Statement