You have to loop on recv until you’ve got a complete message. Typically you’d do that with a recursive function. It receives the data, adds it to what has already been received, then checks to see if it is a complete command. If so it dispatches that to whatever logic is consuming it, otherwise it calls itself passing the accumulated data and blocks on recv again. You’d also want to be counting down with some kind of timeout.
Here you say, that packets shall be exactly one line.
Here, you receive exactly one “packet”.
Be aware that a “line” in gen_tcp (and most other similar IO abstractions on the BEAM) means LF only, not CRLF as you are using it.
As @jeremyjh already pointed out, recursion is the way to go:
def recv_loop(sock) do
case :gen_tcp.recv(sock, 0) do
{:ok, line} ->
IO.puts(data)
recv_loop(sock)
{:error, reason} ->
IO.puts(inspect(reason))
end
end
PS: is there any reason why you call reason |> inspect |> IO.puts rather than IO.inspect(reason)?
This is protocol dependent. You have to parse that data you’ve received and see if it is complete. That means in this case, that it depends on when you get a complete SMTP command/message. You need to read the SMTP standard and implement it.
You need to understand that when you are working at the TCP socket level, you are working at a much lower level than is typically done in application programming. You are implementing a network protocol at the OSI application level.
That is why I mentioned that you need to implement a timeout. You can pass a timeout value to :gen_tcp.recv.
active: true will take messages from the wire as they are available and put them into your mailbox, so if you are not emptying your mailöbox fast enough, you will stress your network stack needlessly and your processes mailbox will flow. TCP has no way to apply backpressure and reduce used bandwith.
Therefore its often suggested to not rely on active: true for everything but only while waiting for waiting for the next communication
True, under load I prefer active: once, false is a good first stab for proof-of-concept. And if your process isn’t under that much load its good enough.