Blocking on NetworkStream.Read()

G

Guest

Hi

I've recently written a .NET client which communicated to a server via a
TcpClient class (from System.Net.Sockets).

One thing I noticed is my call to the GetStream().Read() method is not
blocking.

I've been through a few different sections in the MSDN help as well as a few
books and articles about the TcpClient class and have gotten some conflicting
information.

The information on the ReceiveTimeout property states it will set the
blocking on the NetworkStream.Read() method.

The documention on the NetworkStream.Read() method give the impression that
a call is non-block since it doesn't wait for data to become available before
returning.

I've looked at a number of samples of using the TcpClient class at various
sites and all appear to be written as if the Read method will block.

Does anyone know if there are specific conditions which may be affecting
this behaviour (i.e. additional properties or server / network factors)?

Thanks in advance

Al
 
P

Peter Duniho

I've recently written a .NET client which communicated to a server via a
TcpClient class (from System.Net.Sockets).

One thing I noticed is my call to the GetStream().Read() method is not
blocking.

What do you mean that it "is not blocking"? If you mean that it is
returning immediately without reading any data, then I find that difficult
to believe. The only time this should happen is when the end of the
stream is reached, when it will return 0 for the bytes read.

If you mean that it is returning before it has read _all_ of the data that
is or will be sent on the stream, then yes. This is documented, by design
behavior. Stream.Read() is guaranteed only to return at least one byte,
as long as you have not reached the end of the stream.

http://msdn2.microsoft.com/en-us/library/system.io.filestream.read.aspx

Pete
 
G

Guest

Hi

What is basically happening is if I do an immediate Read after I write to
the network stream. Read returns immediately with an empty buffer[]
regardless of the value I enter in the ReceiveTimeout property (10000 ms). If
I however introduce a delay between the write and read (either via a break
point or Thread.Sleep) the read operation returns me the data from the
network.

I have coded around this currently by swapping out the TcpClient for a
Socket class and executing Read on the Socket class. This now blocks until
the buffer has either started receiving data from the network or the timeout
expires.

Many thanks

AL
 
P

Peter Duniho

What is basically happening is if I do an immediate Read after I write to
the network stream. Read returns immediately with an empty buffer[]
regardless of the value I enter in the ReceiveTimeout property (10000
ms). If
I however introduce a delay between the write and read (either via a
break
point or Thread.Sleep) the read operation returns me the data from the
network.

I have coded around this currently by swapping out the TcpClient for a
Socket class and executing Read on the Socket class. This now blocks
until
the buffer has either started receiving data from the network or the
timeout
expires.

Huh.

As much as I hate to say it (I'm always writing "it's not a bug in .NET"
because so many people are accusing .NET of having a bug when it's in
their own code :) ), I think maybe in this case you've found a bug in .NET.

It _seems_ to me that the NetworkStream() you get frmo TcpClient should be
exactly equivalent to the NetworkStream() you can get from a Socket. So
if the Socket works fine but the TcpClient does not when doing the same
exact thing, I'd say the TcpClient is broken somehow.

One minor point: you mention setting the ReceiveTimeout property. I don't
think that this should result in, or somehow prevent, the call to Read()
completing immediately. However, do keep in mind that if you set a
timeout for receiving, that if the timeout occurs, the socket is no longer
usable. I believe the same thing is true for TcpClient. If you want a
timeout, but want to be able to continue waiting for data on the socket
afterwards, you'll want to implement your own timeout logic (which would
require using asynchronous methods) rather than using the ReceiveTimeout
property.

Pete
 
G

Guest

Hi

Thanks for the feedback. I would like to hope it's not a framework bug,
however am happy that I have gotten some more information.

Many thanks


Peter Duniho said:
What is basically happening is if I do an immediate Read after I write to
the network stream. Read returns immediately with an empty buffer[]
regardless of the value I enter in the ReceiveTimeout property (10000
ms). If
I however introduce a delay between the write and read (either via a
break
point or Thread.Sleep) the read operation returns me the data from the
network.

I have coded around this currently by swapping out the TcpClient for a
Socket class and executing Read on the Socket class. This now blocks
until
the buffer has either started receiving data from the network or the
timeout
expires.

Huh.

As much as I hate to say it (I'm always writing "it's not a bug in .NET"
because so many people are accusing .NET of having a bug when it's in
their own code :) ), I think maybe in this case you've found a bug in .NET.

It _seems_ to me that the NetworkStream() you get frmo TcpClient should be
exactly equivalent to the NetworkStream() you can get from a Socket. So
if the Socket works fine but the TcpClient does not when doing the same
exact thing, I'd say the TcpClient is broken somehow.

One minor point: you mention setting the ReceiveTimeout property. I don't
think that this should result in, or somehow prevent, the call to Read()
completing immediately. However, do keep in mind that if you set a
timeout for receiving, that if the timeout occurs, the socket is no longer
usable. I believe the same thing is true for TcpClient. If you want a
timeout, but want to be able to continue waiting for data on the socket
afterwards, you'll want to implement your own timeout logic (which would
require using asynchronous methods) rather than using the ReceiveTimeout
property.

Pete
 

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