Long story short I am trying to send a string via TcpClient using StreamWriter.
Without changing any other code except swapping out these samples. They produce different results.
In code sample 1 the StreamReader picks up that it has DataAvailable and the message is received.
In code sample 2 it does not have DataAvailable so no message is received. I need to keep my underlying stream open hence needing to use the constructor of StreamWrite in sample 2.
Sample 1 - Write Method
public void SendMessage(string message)
{
message = "TestMessage";
//WORKING - Sample 1
using (var sw = new StreamWriter(stream))
{
sw.Write(message);
sw.Flush();
}
}
Sample 2 - Write Method
public void SendMessage(string message)
{
message = "TestMessage";
//NOT WORKING - Sample 2
var encoding = new UTF8Encoding(false, true);
using (var sw = new StreamWriter(stream, encoding, 1024, true))
{
sw.Write(message);
sw.Flush();
}
}
Read Method
public string ReadMessage()
{
if (!stream.DataAvailable)
return null;
//I have also tried
//if(sr.Peek() == 0)
// return null;
string message = sr.ReadToEnd();
return message;
}
NOTE: If I put both samples together with the working one last I get the message received "TestMessageTestMessage" so it is definitely writing to stream however it is not setting DataAvailable to true?
Any Idea's why?
The problem is your ReadToEnd()
command which blocks indefinitely on a NetworkStream
which has no end until closed. I tested your code and I went past the DataAvailable
query and blocked on the ReadToEnd()
command.
Your method that uses a constructor that allows the BaseStream
to stay open means that you never have an end to your stream. When the working method closes the stream the ReadMessage
method returns with everything in the stream.
The solution: Do not attempt to read to the end. Read in blocks while the data is available or introduce a terminating character and read to that character.
From MSDN:
ReadToEnd assumes that the stream knows when it has reached an end. For interactive protocols in which the server sends data only when you ask for it and does not close the connection, ReadToEnd might block indefinitely because it does not reach an end, and should be avoided.