.NET 2.0 NetworkStream.DataAvailable returning false

G

Guest

I'm using .NET2.0 to connect to a remote networked device. The device
accepts commands terminated with CRLF characters and responds with multiple
lines of data each terminated with CRLF.

Following the issue of a command I am finding that I am not receiving all of
the data, it simply stops receiving.

I use the DataAvailable property to check for the existance of data before
attempting to read.

The following code snippet shows how I am reading the data:

TCPClient netClient;
NetworkStream netStream;
NetworkReader netReader;

// Connet TCPClient
....

// Get stream fromTCPClient
netStream = netClient.GetStream();

// Create the stream reader
netReader = new StreamReader(netStream);

while (!exit)
{
if (netClient != null && netClient.Connected && netStream.DataAvailable)
{
dataToRead = true;
}

if (dataToRead)
{
// There is data available, read it
data = netReader.ReadLine();

// Process data
...
}
}

I am finding that occasionally the DataAvailable property simply returns
false and then continuously returns false, therefore the ReadLine method is
never called and the code performs a timeout.

When the DataAvailable property returns false I can still issue a ReadLine
and data is returned but DataAvailable remains false.

I have had to resort to checking the StreamReader.Peek() response as well as
NetworkStream.DataAvailable. The behaviour of each of independently is
inconsistant.

The following code will read all data:

TCPClient netClient;
NetworkStream netStream;
NetworkReader netReader;

// Connet TCPClient
....

// Get stream fromTCPClient
netStream = netClient.GetStream();

// Create the stream reader
netReader = new StreamReader(netStream);

while (!exit)
{
if (netClient != null && netClient.Connected)
{
if (netStream.DataAvailable != 0 || netReader.Peek() != -1)
{
dataToRead = true;
}
}

if (dataToRead)
{
// There is data available, read it
data = netReader.ReadLine();

// Process data
...
}
}

Can anyone explain this ?

Regards

Steve
 
W

William Stacey [MVP]

DataAvailable is not a blocking call. It just returns 0 if no current bytes
are available at that second. For this reason, it is not of much use. It
is simplier to block on a Receive() and know the other side is done either
when Receive returns 0 bytes or you have received all the data you expected.
The samples I have seen using DataAvailable are not correct.
 
G

Guest

William,

I've also found that a lot of the sample in the VS Help also don't really
work. A lot of samples loop around the Peek() method.

e.g.

while(streamReader.Peek() != -1)
{
//Read bytes
buf = streamReader.Read();
}

I found that frequently the Peek() function is also un-reliable.

Would you suggest to simply read on a background thread and let the Read()
method block ?

Steve
 
W

William Stacey [MVP]

That is what I would do. Something like this on another thread:
public static long ReadToStream(Socket s, Stream stream, long size)
{
int blockSize = 1024;
long bytesRead = 0;
int read = 0;
byte[] buf = new byte[blockSize];

while ( bytesRead < size )
{
read = s.Receive(buf);
// check 0.
stream.Write(buf, 0, read);
bytesRead += read;
}
return bytesRead;
}
 

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