gen_tcp send non-blocking in erlang?

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Vinoth Kumar
Does gen_tcp supports non-blocking send ?I have tried gen_tcp:send which returns the ok while the packets has not been sent to the receiver. Whether any mechanism in erlang to check the sent message delivary?
Thanks,Vinoth Kumar J    
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/b70a29e3/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Max Lapshin
It is a very, very dangerous practice, because you loose control over your
program with non-blocking send.

First step that you MUST do is setting send_timeout on socket. By default
it is infinity and it means that your process may get blocked forever
trying to push data.

I don't know why infinity is a default value, it is really strange for me.

Second, dangerous step is just using port_command(Socket, IoData). Then you
must wait for messages from this socket. But don't use it =)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/4061e867/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Vinoth Kumar
I have used both first and second step requested (i.e. {send_timeout,0} and erlang:port_command(Socket,Data)) but these methods also returns the same. Returns OK while tcp packets has not been delivered(i.e. TCP ack not received). The packet is pushed into the queue and trying to send. So i want an async send mechanism to check whether the  packet has been sent to receiver. If packet delivered means just returns ok otherwise will return {error,timeout}
Thanks,Vinoth Kumar J
Date: Mon, 17 Mar 2014 12:53:41 +0400
Subject: Re: [erlang-questions] gen_tcp send non-blocking in erlang?
From: max.lapshin
To: vinothsparrow
CC: erlang-questions

It is a very, very dangerous practice, because you loose control over your program with non-blocking send.
First step that you MUST do is setting send_timeout on socket. By default it is infinity and it means that your process may get blocked forever trying to push data.

I don't know why infinity is a default value, it is really strange for me.
Second, dangerous step is just using port_command(Socket, IoData). Then you must wait for messages from this socket. But don't use it =)

     
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/01b73065/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Matthias Lang-2
In reply to this post by Vinoth Kumar
Hi,

Here's an earlier discussion on the same topic:

  https://groups.google.com/forum/#!topic/erlang-programming/pSN3Cl0bBTg

You can use 'send_timeout', but note the warning in the fine manual:

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

it's basically telling you that the only well-defined thing you can do
after send_timeout is to close the socket.

Another, less satisfactory, approach is to write code like this:

    {ok, Tref} = timer:apply_after(500, erlang, exit, [self(), kill]),
    gen_tcp:send(S, Data),
    timer:cancel(Tref).

---

You haven't really told us what you actually want to do. It could be
that what you want isn't really possible at all, at least not with the
conventional interface to the OS' TCP stack---there are buffers in the
OS and buffers in the Erlang VM which you don't have complete control
over.

If feel you need to heed the dramatic warnings in Max's post, you
should probably ask him to clarify.

Matthias

-----------------------------------------
Date: Monday, March 17
From: Vinoth Kumar <vinothsparrow>
To erlang-questions
Subject: [erlang-questions] gen_tcp send non-blocking in erlang?


> Does gen_tcp supports non-blocking send ?I have tried gen_tcp:send which returns the ok while the packets has not been sent to the receiver. Whether any mechanism in erlang to check the sent message delivary?
> Thanks,Vinoth Kumar J

> _______________________________________________
> erlang-questions mailing list
> erlang-questions
> http://erlang.org/mailman/listinfo/erlang-questions


Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Max Lapshin
In reply to this post by Vinoth Kumar
As far as I remember, Unix API doesn't give you any ability to tell that
you have received ACK.

There are many reasons. One of them is that TCP socket is a pipe only from
application point of view. Kernel sees TCP as a window: some fragments of
window are received, some are not. When to notify you? When all buffer is
sent?
Perhaps in such way your application will be very inefficient, because you
will have to spend more time fetching data from remote server or local disk
and send again.


Maybe you should take a look at some application level confirm? "Hey there
is a packet #145", "Thanks, I've received #145".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/3a837dce/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Vinoth Kumar
Thanks Max,
I will do it with application level confirmation. :)
Date: Mon, 17 Mar 2014 14:29:56 +0400
Subject: Re: [erlang-questions] gen_tcp send non-blocking in erlang?
From: max.lapshin
To: vinothsparrow
CC: erlang-questions

As far as I remember, Unix API doesn't give you any ability to tell that you have received ACK.
There are many reasons. One of them is that TCP socket is a pipe only from application point of view. Kernel sees TCP as a window: some fragments of window are received, some are not. When to notify you? When all buffer is sent?
Perhaps in such way your application will be very inefficient, because you will have to spend more time fetching data from remote server or local disk and send again.


Maybe you should take a look at some application level confirm? "Hey there is a packet #145", "Thanks, I've received #145".

     
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/a64ecfc1/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Jesper Louis Andersen
In reply to this post by Vinoth Kumar
On Mon, Mar 17, 2014 at 8:15 AM, Vinoth Kumar <vinothsparrow>wrote:

> Does gen_tcp supports non-blocking send ?
>
> I have tried gen_tcp:send which returns the ok while the packets has not
> been sent to the receiver. Whether any mechanism in erlang to check the
> sent message delivary?
>

I think you must consider you may be going in a direction which TCP does
not support, in general. The danger is you end up in a situation where you
are bending the rules of TCP to a point where the guarantee you expect is
not even there. Only turmoil is on this path.

The problem is Erlang can only see so far. Once it delivers data to the
kernel, the kernel is in control of what happens and you have relatively
few ways to ask the kernel what it is doing. Worse, even if the kernel
manages to send data, the NIC might queue you. Modern NICs have buffers in
the excess of 4096 packets. And you have even fewer ways to ask those about
their state. And if the NIC manages to send data, the hops in route might
queue you.


--
J.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140317/2b6c1322/attachment.html>

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Jon Meredith
In reply to this post by Vinoth Kumar
> Whether any mechanism in erlang to check the sent message delivary?
> Thanks,Vinoth Kumar J

TCP doesn't so how can Erlang ?

I was quite shocked to find that a colleague of mine who has worked in
mobile comms for years thought that TCP write()/send() returned when data
was delivered rather than queued.

Jon


Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Matthias Lang-2
On Monday, March 17, Jon Schneider wrote:

> > Whether any mechanism in erlang to check the sent message delivary?

> TCP doesn't so how can Erlang ?

[This is going beyond what the original poster probably had in mind, but
it's an interesting problem.]

TCP _does_ know which data has been ACKed. But that information gets
lost somewhere between the TCP stack and ordinary programs.

Something like this:

   http://www.erlang.se/workshop/2005/tcpip_presentation.pdf

could be tweaked so that it really does let Erlang code figure out whether
or not a particular byte has reached the remote TCP stack.

Matthias

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Loïc Hoguin-2
On 03/17/2014 12:19 PM, Matthias Lang wrote:

> On Monday, March 17, Jon Schneider wrote:
>
>>> Whether any mechanism in erlang to check the sent message delivary?
>
>> TCP doesn't so how can Erlang ?
>
> [This is going beyond what the original poster probably had in mind, but
> it's an interesting problem.]
>
> TCP _does_ know which data has been ACKed. But that information gets
> lost somewhere between the TCP stack and ordinary programs.
>
> Something like this:
>
>     http://www.erlang.se/workshop/2005/tcpip_presentation.pdf
>
> could be tweaked so that it really does let Erlang code figure out whether
> or not a particular byte has reached the remote TCP stack.

But the packet may be lost between the remote stack and the remote
program, due to any number of reasons, including bugs and crashes. A way
to know a remote endpoint has truly received the packet and processed it
is to make it send a packet back. But even that is not perfect, as that
"ack" packet can also be lost.

A common way to solve this is to have an auto incremented value for all
messages sent, and if the remote endpoint disconnects for any reasons,
have it send the last value it received when connecting so the local
endpoint knows what it needs to send again.

--
Lo?c Hoguin
http://ninenines.eu

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Carsten Bormann
In reply to this post by Matthias Lang-2
On 17 Mar 2014, at 12:19, Matthias Lang <matthias> wrote:

> TCP _does_ know which data has been ACKed. But that information gets
> lost somewhere between the TCP stack and ordinary programs.

Not really.  Look up ?connection-splitting PEP?.

> Something like this:
>
>   http://www.erlang.se/workshop/2005/tcpip_presentation.pdf
>
> could be tweaked so that it really does let Erlang code figure out whether
> or not a particular byte has reached the remote TCP stack.

And that is useful how?

The process reading from the socket could crash any moment after that.

(This discussion seems to conflate misusing transport acknowledgments for application-level acknowledgment with flow control.
The latter *is* important, and appears to have somewhat strange solutions, if at all, in the Erlang world.)

Gr??e, Carsten


Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Matthias Lang-2
On Monday, March 17, Carsten Bormann wrote:

Carsten> Not really.  Look up ?connection-splitting PEP?.
...
> > could be tweaked so that it really does let Erlang code figure out whether
> > or not a particular byte has reached the remote TCP stack.

> And that is useful how?

How does a connection-splitting PEP (i.e. what you referred to above)
decide how much data to allow in from the fixed/fast side? Does it
just use a static buffer, or does it keep an eye on how much the
mobile/slow side's TCP stack has ACKed? If the latter, then that's an
example of where this information would be useful.

Matthias

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Geoff Cant
In reply to this post by Vinoth Kumar
gen_tcp is a wrapper around functionality provided by a prim_inet port - and in fact gen_tcp implements a synchronous call interface to the underlying asynchronous message based port API, so if you are prepare to thoroughly void your warranty, you can do async tcp sends in Erlang.

A testament to my sins^W^W^W^Wworked example can be seen here: https://github.com/heroku/logplex/blob/master/src/logplex_tcpsyslog_drain.erl#L565, https://github.com/heroku/logplex/blob/master/src/logplex_tcpsyslog_drain.erl#L224

* erlang:port_command(TcpSocket, DataToSend, []) % Start async send
* receive {inet_reply, TcpSocket, Result} -> something() end % finish async send - result is 'ok' or {'error', Why}

You buy yourself a whole lot of hurt with this - you have to manage all your own timeouts and error detection behaviour. The upside is that the process doing the sending doesn't need to block on a selective receive, so can continue doing work (clearing a noisy incoming message queue in my example above).


tl;dr: yes, it can be done but think twice before doing so, and don't bug the OTP team if it goes wrong - they tried to warn us :)

-Geoff
 

On 2014-03-17, at 00:15 , Vinoth Kumar <vinothsparrow> wrote:

> Does gen_tcp supports non-blocking send ?
>
> I have tried gen_tcp:send which returns the ok while the packets has not been sent to the receiver. Whether any mechanism in erlang to check the sent message delivary?
>
>
>
> Thanks,
>
> Vinoth Kumar J
>





Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Fred Hebert
To note that erlang:port_command(TcpSocket, DataToSend, []) will
deschedule the process (and leave it that way) when the buffer is full.
The alternative is to pass in the 'nosuspend' option, which will avoid
the issue, but will return true/false depending on if it was possible to
send the packet to the buffer.

On 03/17, Geoff Cant wrote:

> gen_tcp is a wrapper around functionality provided by a prim_inet port - and in fact gen_tcp implements a synchronous call interface to the underlying asynchronous message based port API, so if you are prepare to thoroughly void your warranty, you can do async tcp sends in Erlang.
>
> A testament to my sins^W^W^W^Wworked example can be seen here: https://github.com/heroku/logplex/blob/master/src/logplex_tcpsyslog_drain.erl#L565, https://github.com/heroku/logplex/blob/master/src/logplex_tcpsyslog_drain.erl#L224
>
> * erlang:port_command(TcpSocket, DataToSend, []) % Start async send
> * receive {inet_reply, TcpSocket, Result} -> something() end % finish async send - result is 'ok' or {'error', Why}
>
> You buy yourself a whole lot of hurt with this - you have to manage all your own timeouts and error detection behaviour. The upside is that the process doing the sending doesn't need to block on a selective receive, so can continue doing work (clearing a noisy incoming message queue in my example above).
>
>
> tl;dr: yes, it can be done but think twice before doing so, and don't bug the OTP team if it goes wrong - they tried to warn us :)
>
> -Geoff
>  
>
> On 2014-03-17, at 00:15 , Vinoth Kumar <vinothsparrow> wrote:
>
> > Does gen_tcp supports non-blocking send ?
> >
> > I have tried gen_tcp:send which returns the ok while the packets has not been sent to the receiver. Whether any mechanism in erlang to check the sent message delivary?
> >
> >
> >
> > Thanks,
> >
> > Vinoth Kumar J
> >
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions
> http://erlang.org/mailman/listinfo/erlang-questions

Reply | Threaded
Open this post in threaded view
|

gen_tcp send non-blocking in erlang?

Richard A. O'Keefe
In reply to this post by Carsten Bormann

On 18/03/2014, at 12:29 AM, Carsten Bormann wrote:
>
> Not really.  Look up ?connection-splitting PEP?.

I did.  Practically everything that came back was a patent.
Would you care to elaborate?