TcpClient / NetworkStream not failing on write?

D

david.topham

Hi

The code below demostrates an issue I'm having with with NetworkStream:

using System;
using System.Net.Sockets;

namespace TCPCTest
{
class Class1
{
static void Main(string[] args)
{
TcpClient tcpc = new TcpClient();
tcpc.Connect("localhost", 15015);

byte[] bytearray = new byte[4];
bytearray[0] = (byte)0;
bytearray[1] = (byte)1;
bytearray[2] = (byte)2;
bytearray[3] = (byte)3;

Console.WriteLine("Sleeping for 10s...");
// While the thread is sleeping, kill the receiving process
System.Threading.Thread.Sleep(10000);

NetworkStream ns = tcpc.GetStream();
try
{
Console.WriteLine("Write 1");
ns.Write(bytearray, 0, 4);
Console.WriteLine("Write 1 OK");
Console.WriteLine("Write 2");
ns.Write(bytearray, 0, 4);
Console.WriteLine("Write 2 OK");
}
catch (System.Exception e)
{
Console.WriteLine("Exception");
Console.WriteLine(e);
}

ns.Close();
tcpc.Close();
}
}
}

This isn't production code, but it demonstrates the problem I'm having
with in my app. The code connects to a remote process listening for
connections on local port 15015, although it could be any port on any
address. It then sleeps for 10s - use this time to kill the remote app,
pull out the network cable, or whatever it takes to break the
connection.

The code then makes two calls to NetworkStream.Write. An exception
should be thrown because the write is not possible. But it's always the
second Write that throws the IOException, never the first. As far as
you can tell, the first write is successful. I've tried setting NoDelay
on the TCPClient to no effect. I've also tried changing the SendBuffer
size. Adding calls to Flush makes no difference, as Flush on
NetworkStream does nothing (see the docs).

Any idea why the first write doesn't fail?

Thanks

David Topham
 
N

Nick Hounsome

The first write does not fail because it does not wait for the TCP frames to
be acknowledged before returning.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Any idea why the first write doesn't fail?

Probably cause the TCP stack has no idea yet that the remote connection is
dead, it just sent the first package and is waiting for the ACK, maybe if
your buffer is small and you send a big chunk of data in your first line you
get the error right there.

BTW, I don't see what is the big issue if you are getting the exception
anyway
 
D

david.topham

I see your point, although it's not much help if I only want to make
one call to Write. I only made two in the code to demonstrate the
issue.

BTW, I tried setting the SendBuffer size to 4 bytes, and sending though
a 1000 byte buffer on the Write calls - the first call still did not
fail.

David
 
D

david.topham

I see your point, although it's not much help if I only want to make
one call to Write. I only made two in the code to demonstrate the
issue.

BTW, I tried setting the SendBuffer size to 4 bytes, and sending though
a 1000 byte buffer on the Write calls - the first call still did not
fail.

David
 
N

Nick Hounsome

I see your point, although it's not much help if I only want to make
one call to Write. I only made two in the code to demonstrate the
issue.

You would get the error when you closed the socket.

If you really want positive acknowledgement that some data has been received
then you have to do it yourself.
BTW, I tried setting the SendBuffer size to 4 bytes, and sending though
a 1000 byte buffer on the Write calls - the first call still did not
fail.

It probably ignored you. Apart from anything else the minimum IP datagram
size that must be supported by any system is 576 bytes so I see no way that
it wouold accept less than this (minus header size). Try checking to see
what size it actually used.
 
V

Vadym Stetsyak

Hello, (e-mail address removed)!

dt> BTW, I tried setting the SendBuffer size to 4 bytes, and sending though
dt> a 1000 byte buffer on the Write calls - the first call still did not
dt> fail.

This can be due to 'nagling' ( SocketOptionName.NoDelay ).


--
Regards, Vadym Stetsyak
www: http://vadmyst.blogspot.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top