如何通过C#中的XmlReader的ReadAsync从NetworkStream解析XML? [英] How do I parse XML from NetworkStream via ReadAsync of XmlReader in C#?

查看:210
本文介绍了如何通过C#中的XmlReader的ReadAsync从NetworkStream解析XML?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过C#中NetworkStream类的BeginRead从OpenFire服务器读取以NetworkStream形式接收的XML,并使用以下代码(我每1024个字节对其进行调用,以为其提供更多XML部分,保存在data(即byte[])中.

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;
        }
    }
}

我收到的不完整" XML如下所示.

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>

我有2个例外.

  • System.Xml.XmlException:'.'(十六进制值0x00)是无效字符
  • System.Xml.XmlException:'stream'是未声明的前缀

为什么我会收到这些例外?我该如何解决?

Why am I getting these exceptions? How do I fix them?

我尝试使用ConformanceLevel = ConformanceLevel.Fragment,但这似乎与它无关.

I tried using ConformanceLevel = ConformanceLevel.Fragment but this seems to have nothing to do with it.

也许我正在使用XmlReader及其ReadAsync方法完全错误?直接从NetworkStream读取是否更好(如果是这种情况,如何正确完成操作)?

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)?

目前,我正在调用上述代码,就像每隔1024个字节(缓冲区大小)一样.

Currently I am calling the above code like follows every 1024 bytes (size of the buffer).

private void EndReceive(IAsyncResult asyncResult)
{
    ...
    HandleXMLInput(buffer, nBytes);
    ...
}

更新:

我刚刚意识到根本不需要BeginReceive/EndReceive.仅打开NetworkStream,然后在AsyncRead中等待来自网络的数据就足够了(woohoo!;)).以下代码将其总结.

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();

    ...
}

推荐答案

似乎您是在其他地方解码流,然后将其分块地馈送到XmlReader.因为每次您都要为每个块创建一个新的XmlReader,所以在第一个块之后,您将把损坏的Xml馈送到需要格式良好的文档的过程中.

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;
        }
    }
}

要清楚:在将流传递给XmlReader之前,不需要对流进行任何其他读取.当您呼叫ReadAsync时,阅读器会代您处理所有读取操作.

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.

这篇关于如何通过C#中的XmlReader的ReadAsync从NetworkStream解析XML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆