I'm reading continuously from a TcpClient streamreader. The data coming from the stream is raw XML. There is no message framing. So there is now reliable method to know when the message is finished. Though I only have 3 XML messages coming from the server. But when they are coming is unknown. And I can't configure/program the server. This is my code so far.
public void Start()
{
StreamReader reader = new StreamReader(_tcpClient.GetStream());
char[] chars = new char[Int16.MaxValue];
while (!_requestStop)
{
try
{
while ((reader.Read(chars, 0, chars.Length)) != 0)
{
string s = new string(chars);
s = removeEmptyChars(s);
if (s.IndexOf("<foo", StringComparison.OrdinalIgnoreCase) > 0 &&
s.IndexOf("</foo>", StringComparison.OrdinalIgnoreCase) > 0)
{
Console.WriteLine(s);
OnAlarmResponseComplete(new CustomEventArgs(s));
}
if (s.IndexOf("<bar", StringComparison.OrdinalIgnoreCase) > 0 &&
s.IndexOf("</bar>", StringComparison.OrdinalIgnoreCase) > 0)
{
Console.WriteLine(s);
OnAckComplete(new CustomEventArgs(s));
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//break;
}
}
reader.Close();
Console.WriteLine("Stopping TcpReader thread!");
}
Then in my main thread I'm processing the events. I'm adding them to a list. Where I process the list. When I'm debugging my application, I will be receiving 10 foo and 10 bar messages. And in my lists I have only 1 foo and 1 bar message stored.
Are the eventhandlers to slow to process this? Or am I missing something?
Here is the code you should use to cover all kinds of input issues (foo or bar received partially, foo and bar received together, etc..)
I can't say I approve using string parsing to handle XML content, but anyways.
private static string ProcessAndTrimFooBar(string s, out bool foundAny)
{
foundAny = false;
int fooStart = s.IndexOf("<foo", StringComparison.OrdinalIgnoreCase);
int fooEnd = s.IndexOf("</foo>", StringComparison.OrdinalIgnoreCase);
int barStart = s.IndexOf("<bar", StringComparison.OrdinalIgnoreCase);
int barEnd = s.IndexOf("</bar>", StringComparison.OrdinalIgnoreCase);
bool fooExists = fooStart >= 0 && fooEnd >= 0;
bool barExists = barStart >= 0 && barEnd >= 0;
if ((fooExists && !barExists) || (fooExists && barExists && fooStart < barStart))
{
string fooNodeContent = s.Substring(fooStart, fooEnd - fooStart + 6);
s = s.Substring(fooEnd + 6);
Console.WriteLine("Received <foo>: {0}", fooNodeContent);
OnAlarmResponseComplete(new CustomEventArgs(fooNodeContent));
foundAny = true;
}
if ((barExists && !fooExists) || (barExists && fooExists && barStart < fooStart))
{
string barNodeContent = s.Substring(barStart, barEnd - barStart + 6);
s = s.Substring(barEnd + 6);
Console.WriteLine("Received <bar>: {0}", barNodeContent);
OnAckComplete(new CustomEventArgs(barNodeContent));
foundAny = true;
}
return s;
}
public static void Start()
{
StreamReader reader = new StreamReader(_tcpClient.GetStream());
char[] chars = new char[Int16.MaxValue];
while (!_requestStop)
{
try
{
int currentOffset = 0;
while ((reader.Read(chars, currentOffset, chars.Length - currentOffset)) != 0)
{
string s = new string(chars).TrimEnd('\0');
bool foundAny;
do
{
s = ProcessAndTrimFooBar(s, out foundAny);
} while (foundAny);
chars = s.PadRight(Int16.MaxValue, '\0').ToCharArray();
currentOffset = s.Length;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//break;
}
}
reader.Close();
Console.WriteLine("Stopping TcpReader thread!");
}