Following my last message, I notice something that appears to be a larger
issue to me: basically, I have two methods to send a large byte array
over a socket. I can create a bytes.Buffer() and either io.Copy() it
to the TCPConn or do many io.Copyn().
And the behaviour of both is different when I set a timeout on the TCP
connection. In the attached code, I have a client that reads at a
specific transfer rate from a server that sends 10 million bytes. When
using io.Copy() to send the buffer, I am getting a timeout if the client
does not read *fast enough*.
With a large io.Copy() :
$ ./test2
accept: %!s(<nil>)
server: write tcp 192.168.1.4:49344: resource temporarily unavailable
after 3784704 bytes
client: EOF
With many small io.Copyn(), the expected behaviour
$ ./test2
accept: %!s(<nil>)
server: EOF after 10000000 bytes
client: EOF
When having a look at the source code for io.Copy() and
TCPConn.ReadFrom(), it didn't seem to me that there would be any
difference between the two approches. (I m using Go r59 in a Linux
mchine).
Regards,
--
R�my.
That said, I know no one will go for that.
Please run your program under strace -f
and see where the error comes from.
If it's a partial write that we're not handling
correctly, we should fix that.
Russ
I ran
strace -f -r -e read,write ./test2
and got the attached output.
The first write is :
write(8, "\0\0\0"..., 10000000) = 65536
which is a bit puzzling.
Now the things seem clearer: the netFD struct receives
a giant write, and the (*netFD)Write() function loops until
the whole buffer has been written. Since the deadlines are
not reset after a partial write (which is probably a desirable
feature to avoid extremely slow peers), the routine times out.
It is probably specific to the case where I
io.Copy(net.TCPConn, buffer.Buffer)
since bytes.Buffer implements io.WriterTo interface, and
TCPConn.ReadFrom() is ignored unless it can sendfile().
Maybe it would be a good idea to implement a ReadFrom()
with a reasonable buffer size. I'm not sure relying on
WriteTo() being smart enough to have an adequate buffer size
is good for a network connection.
I see (*bytes.Buffer)WriteTo(...) is just
w.Write(b.buf[b.off:])
which confirms the origin of the giant write.
Regards,
--
R�my
Russ
There is an argument that you should still timeout. For example, in a
web server, you could have someone DOS you by making lots of
connections for very big contents, and then consume the result at the
slowest rate possible (1byte per second, etc.)
I think a better answer is: "don't send 100MB in a single write call".
At least IMO.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk5WGcwACgkQJdeBCYSNAAMSIwCgllTlM5sftQM0SqNy757XlZlz
m2IAnjGhhTE40/WECk+8ykKmivLzDWU2
=m8KG
-----END PGP SIGNATURE-----