Reputation: 2468
I am trying to read in XML that I receive as NetworkStream
from an OpenFire server via BeginRead
of the NetworkStream
class in C# with following code (I call it every 1024 bytes to give it more XML parts which are saved in data
(which is byte[]
)).
using (var r = XmlReader.Create(new StringReader(Encoding.UTF8.GetString(data)),
new XmlReaderSettings() { Async = true }))
{
while (await r.ReadAsync())
{
switch (r.NodeType)
{
case XmlNodeType.Element:
Console.WriteLine(r.LocalName);
break;
case XmlNodeType.Text:
Console.WriteLine(await r.GetValueAsync());
break;
}
}
}
The 'incomplete' XML I am receiving looks like follows.
<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="blah" id="d6c0a0b8" xml:lang="en" version="1.0">
<stream:features>
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>ANONYMOUS</mechanism>
<mechanism>CRAM-MD5</mechanism>
</mechanisms>
<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>
<auth xmlns="http://jabber.org/features/iq-auth"/>
<register xmlns="http://jabber.org/features/iq-register"/>
</stream:features>
I am getting 2 exceptions.
Why am I getting these exceptions? How do I fix them?
I tried using ConformanceLevel = ConformanceLevel.Fragment
but this seems to have nothing to do with it.
Maybe I am using XmlReader
and its ReadAsync
method completely wrong? Would it be better to read directly from the NetworkStream
(if this is the case how is it done correctly)?
Currently I am calling the above code like follows every 1024 bytes (size of the buffer).
private void EndReceive(IAsyncResult asyncResult)
{
...
HandleXMLInput(buffer, nBytes);
...
}
Update:
I just realized that no BeginReceive/EndReceive is needed at all. It is sufficient to just open the NetworkStream
and then wait for data coming from the network in AsyncRead
(woohoo! ;)). The following code sums it up.
socket.BeginConnect(endPoint, new AsyncCallback(EndConnect), null);
private void EndConnect(IAsyncResult asyncResult)
{
...
socket.EndConnect(asyncResult);
networkStream = new NetworkStream(socket, false);
HandleXMLInput();
...
}
Upvotes: 2
Views: 3873
Reputation: 120450
It seems that you are decoding the stream elsewhere then feeding it in chunks to XmlReader. Because each time, you're creating a new XmlReader for every chunk, after the first chunk, you'll be feeding broken Xml to a process that expects a well-formed document.
Why not save a whole bunch of coding and heartache by reading the stream directly?
using(var r = XmlReader.Create(myNetworkStream))
{
//await r.ReadAsync() only returns false at the end of the document
//so this loop will read the whole document
while (await r.ReadAsync())
{
switch (r.NodeType)
{
case XmlNodeType.Element:
Console.WriteLine(r.LocalName);
break;
case XmlNodeType.Text:
Console.WriteLine(await r.GetValueAsync());
break;
}
}
}
to be clear: you don't need to do any additional reading of the stream before passing it to the XmlReader. The reader takes care of all the read operations on your behalf when you call ReadAsync
.
Upvotes: 2