softarn
softarn

Reputation: 5497

Messages using gen_tcp:send doesn't get sent until the socket is closed

I want to write a simple client that sends a message to a server and receives a response. I've got a server that broadcasts the same message to all connected clients and its working when I'm testing it with telnet. When I try doing it using the Erlang shell, gen_tcp:send wont send any messages until I've close the socket.

This is what I'm trying to do:

{ok, S} = gen_tcp:connect(IP, Port, []).
gen_tcp:send(S, "Test").
flush().

I can see that the message gets sent when I close the socket by looking at my telnet client.

Erlang version:R14B01 (erts-5.8.2)

Update

hdima commented and said that it might be wrong with how the server extract the messages from the stream. This seems to be the case cause when I tried writing my own server the client seems to work as expected. I'll try to get the source code of the server. The server is written in Java btw.

Upvotes: 1

Views: 1611

Answers (3)

Mazen Harake
Mazen Harake

Reputation: 1726

When sending small chunks of data the socket buffers them up to try to fill up the maximum payload for a TCP packet.

It is possible that this is what is going on because when you close the socket it is flushed before it is deallocated.

Try setting the

{nodelay, true}

option on your socket.

More info here: http://www.erlang.org/doc/man/inet.html#setopts-2

Upvotes: 4

hdima
hdima

Reputation: 3637

The main problem is that there is no Universal Message Format. So your first step is to find what message format the server using. You can't speak with the server on a different language.

Some message formats can be:

  • The whole stream is a message.
  • Fixed size messages.
  • Messages delimited by a marker. For example SMTP, POP, HTTP and many other protocols use this type of messages.
  • Messages with a size field. For example TLV (Type-Length-Value) message format. IP, UDP, Erlang and many other protocols use this type of messages.

For example if the server understand messages delimited by the line feed character you can send two distinct messages with the following code:

1> {ok, S} = gen_tcp:connect(IP, Port, []).
2> gen_tcp:send(S, "Test\n").
3> gen_tcp:send(S, "Test2\n").

Upvotes: 3

Adam Lindberg
Adam Lindberg

Reputation: 16577

You can try this out with an Erlang server to see if it is the server or client side that has problems.

In shell A:

1> {ok, L} = gen_tcp:listen(12345, [{active, false}]).
{ok,#Port<0.601>}
2> {ok, S} = gen_tcp:accept(L), {ok, P} = gen_tcp:recv(S, 0), gen_tcp:send(S, P).
... % Server will block here until a message comes
ok

In shell B:

1> {ok, S} = gen_tcp:connect(localhost, 12345, []), gen_tcp:send(S, "hello").
ok
2> flush().
Shell got {tcp,#Port<0.607>,"hello"}

If this works, it's most likely a problem on the Java side.

Upvotes: 1

Related Questions