Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

socket with line buffering

64 views
Skip to first unread message

T.Dieckmann

unread,
Oct 16, 2010, 10:01:29 AM10/16/10
to
Hello,

if I open a socket and configure it with "-blocking 0 -buffering line" I
wonder why a line isn't send over the socket as a separate packet even
if the flush follows the puts command.

e.g.:


for {set i 0} {$i < 50} {incr i} {
puts $socket "line $i"
flush $socket
}
close $socket

I see in the wireshark trace up to ~20 packets containing
only a single line until a large packet is send containing all the
remaining lines.
Is this the expected behaviour if an explicit flush is used here ?

env: ActiveTcl 8.5.9 for Linux (SuSE11.1)

Br,
Torsten

tom.rmadilo

unread,
Oct 16, 2010, 11:39:42 AM10/16/10
to

Since you set buffering to line, you can remove the [flush]. Every
"line" is only flushed to the OS, several lines or even partial lines
may end up in a TCP packet, there is no fixed correlation with your
application level protocol. If the other end reads lines using [gets]
you should get the same number of loop iterations.


Reinhard Max

unread,
Oct 28, 2010, 6:15:21 AM10/28/10
to
Hi,

T.Dieckmann <new...@arcor.de> wrote:

> I see in the wireshark trace up to ~20 packets containing
> only a single line until a large packet is send containing all the
> remaining lines.

this is due to the Nagle algorithm, which tries to reduce the
overhead of sending multiple small packets by collecting the
data coming from the application at the OS level under certain
circumstances.

See http://en.wikipedia.org/wiki/Nagle%27s_algorithm for details.

There is a TIP to expose the API to disable Nagle for a socket
to the Tcl script level, but that's currently targeted for
Tcl 8.7 (http://www.tcl.tk/cgi-bin/tct/tip/344).

As the change is rather small and we already plan to still add
switches for various other aspects of sockets to 8.6, this TIP
should probably also be changed to target 8.6.

BTW, an implementation for Windows has already been committed to
CVS, but it is ifdef'ed out by default. Porting it over to Unix
should be straight-forward.

cu
Reinhard

Alexandre Ferrieux

unread,
Oct 28, 2010, 8:07:51 AM10/28/10
to
On Oct 28, 12:15 pm, Reinhard Max <m...@tclers.tk> wrote:
> Hi,

>
> T.Dieckmann <news...@arcor.de> wrote:
> > I see in the wireshark trace up to ~20 packets containing
> > only a single line until a large packet is send containing all the
> > remaining lines.
>
> this is due to the Nagle algorithm, which tries to reduce the
> overhead of sending multiple small packets by collecting the
> data coming from the application at the OS level under certain
> circumstances.
>
> Seehttp://en.wikipedia.org/wiki/Nagle%27s_algorithmfor details.

>
> There is a TIP to expose the API to disable Nagle for a socket
> to the Tcl script level, but that's currently targeted for
> Tcl 8.7 (http://www.tcl.tk/cgi-bin/tct/tip/344).
>
> As the change is rather small and we already plan to still add
> switches for various other aspects of sockets to 8.6, this TIP
> should probably also be changed to target 8.6.
>
> BTW, an implementation for Windows has already been committed to
> CVS, but it is ifdef'ed out by default. Porting it over to Unix
> should be straight-forward.
>
> cu
> Reinhard

Torsten, while I agree with Reinhard of course, please note that
disabling the Nagle algorithm is only necessary in some specific
situations with very strict latency requirements. I rather read your
message as curiosity about the observed behavior. Bottom line: it is
behaving this way for reasons that are good 99% of the time; if you
feel you're in the 1%, do detailed measurements, look at the ACKs'
timing, and check again. Then you may be in a position to decide that
you need TIP 344 ;-)

-Alex

T.Dieckmann

unread,
Oct 28, 2010, 6:33:09 PM10/28/10
to
Thank you Reinhard and Alex for the further explanation and outlook.

I am within the 99%, but ...
my tcl app has to send messages via tcp to a foreign server. This server
forwards the message to other network connections but also via serial
line to other devices (missing flow control capabilities!).
As long as the messages are send in single packets it works fine. But
once the messages are send within a large packet they are lost.
So I hoped to workaround this by flushing the channel after each puts
statement. As this does not work have to introduce some delay between
each message :-(

Br,
Torsten

Alexandre Ferrieux

unread,
Oct 28, 2010, 6:35:35 PM10/28/10
to
On Oct 29, 12:33 am, "T.Dieckmann" <news...@arcor.de> wrote:
> Thank you Reinhard and Alex for the further explanation and outlook.
>
> I am within the 99%, but ...
> my tcl app has to send messages via tcp to a foreign server. This server
> forwards the message to other network connections but also via serial
> line to other devices (missing flow control capabilities!).
> As long as the messages are send in single packets it works fine. But
> once the messages are send within a large packet they are lost.
> So I hoped to workaround this by flushing the channel after each puts
> statement. As this does not work have to introduce some delay between
> each message :-(

Yes, you'll need to add your delay anyway. Indeed, even with Nagle
disabled, hence individual packets, with fast networks the interpacket
time will be very small, to the same effect.

It's as simple as that: in the absence of flow control, you need a
spacer as close as possible to the receiver. Putting it on the other
side of a network is dangerous.

-Alex

Uwe Klein

unread,
Oct 29, 2010, 5:00:39 AM10/29/10
to

TCP is a _stream_ transport.

If one wants to use it in a packet oriented fashion one would have to
introduce packet delimiters into the stream. Newlines, double newlines
special character sequences, whatever. ..

Anything else is roulette programming.

uwe

0 new messages