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
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.
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
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
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
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
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