jononomo
I can connect using :gen_tcp, but I can't send/receive data - what is wrong with this implementation?
All I want it to do is emulate the following netcat TCP command, which is working properly from my command line:
$ echo "|c country_US" | nc 10.247.4.104 26542
0.500000 <-- response
To accomplish this I have an Elixir module that uses GenServer and :gen_tcp as follows (it has a few extra IO.puts and IO.inspect calls so I can watch progress):
defmodule VowpalWabbex do
use GenServer
def predict(pid, client_data) do
GenServer.call(pid, {:predict, client_data})
end
@initial_state %{socket: nil}
def start_link do
GenServer.start_link(__MODULE__, @initial_state)
end
def init(state) do
IO.puts "VowpalWabbex - init..."
opts = [:binary, :inet, active: false, packet: :line]
{:ok, socket} = :gen_tcp.connect({10, 247, 4, 104}, 26542, opts)
IO.inspect socket
{:ok, %{state | socket: socket}}
end
def handle_call({:predict_adx_inflation, client_data}, _from, %{socket: socket} = state) do
IO.inspect client_data
IO.inspect socket
:ok = :gen_tcp.send(socket, client_data)
IO.puts :ok
{:ok, msg} = :gen_tcp.recv(socket, 0)
{:reply, msg, state}
end
end
I would use this module from within IEX as follows:
$ iex -S mix
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
iex(1)> {:ok, pid} = VowpalWabbex.start_link
VowpalWabbex - init...
#Port<0.6774>
{:ok, #PID<0.238.0>}
iex(2)> VowpalWabbex.predict(pid, "|c country_US")
"|c country_US"
#Port<0.6774>
ok
** (exit) exited in: GenServer.call(#PID<0.238.0>, {:predict, "data"}, 5000)
** (EXIT) time out
So apparently I get an “ok” response when I send the data, but then the I never get a response and instead I time out in a couple of seconds.
Am I doing something wrong in how I’m trying to receive the response?
Thanks much!
Marked As Solved
NobbZ
edit
Please read this before my original post below:
echo in bash always appends a \n (unless told not to do), so, yes, you might need to send it as well.
If that does not work, please consider my original post below.
original post
Your dump only shows header information. I usually dump into a file using -w option. After that I look at the dumps using wireshark. You can inspect package contents then.
Also just removing packet: :line will make things about worse, since the default is packet: 4 as far as I remember, which means that erlang will parse the first 4 byte as unsigned integer and wait for that amount of bytes until it hands the message over to you.
If I were you, I’d try to use packet: :raw for at least a try.
Also Liked
NobbZ
It’s not a wish, its just a warning ![]()
I had to go through similar behaviour as :raw has in a language that didn’t gave me a choice. Even worse I had to make sure I have already allocated buffers large enough to hold the data. And I had to chunk it by my self when I knew previously that my RAM (4 MiB) won’t be enough to process everything at once…
But I do hope, that I do not need to do embedded networking again ![]()
NobbZ
Do not keep :raw unless you have to! It will break your neck if you have a linebased protocol and many concurrent packages to receive!
NobbZ
Does your server send a \n at the end of the package or is it just a fixed with string? That bunch of zeros at the end makes me suspicious…
And again, have you checked using tcpdump and friends what is really sent over the wire?
Last Post!
NobbZ
It’s not a wish, its just a warning ![]()
I had to go through similar behaviour as :raw has in a language that didn’t gave me a choice. Even worse I had to make sure I have already allocated buffers large enough to hold the data. And I had to chunk it by my self when I knew previously that my RAM (4 MiB) won’t be enough to process everything at once…
But I do hope, that I do not need to do embedded networking again ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









