1

我正在尝试使用以下代码读取我通过 C#中的类NetworkStream从 OpenFire 服务器接收到的 XML (我每 1024 个字节调用一次,以提供更多保存在(即)中的 XML 部分)。BeginReadNetworkStreamdatabyte[]

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 如下所示。

<?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:“流”是未声明的前缀

为什么我会收到这些异常?我该如何修复它们?

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

也许我正在使用XmlReader它的ReadAsync方法完全错误?直接从NetworkStream(如果是这种情况下如何正确完成)读取会更好吗?

目前我每 1024 个字节(缓冲区的大小)调用上面的代码。

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

更新:

我刚刚意识到根本不需要 BeginReceive/EndReceive。NetworkStream只需打开然后等待来自网络的数据就足够了AsyncRead(哇哦!;))。下面的代码总结了它。

socket.BeginConnect(endPoint, new AsyncCallback(EndConnect), null);
private void EndConnect(IAsyncResult asyncResult)
{
    ...
    socket.EndConnect(asyncResult);

    networkStream = new NetworkStream(socket, false);

    HandleXMLInput();

    ...
}
4

1 回答 1

2

似乎您正在对其他地方的流进行解码,然后将其分块提供给 XmlReader。因为每次,您都在为每个块创建一个新的 XmlReader,在第一个块之后,您会将损坏的 Xml 提供给需要格式良好文档的进程。

为什么不通过直接读取流来节省一大堆编码和心痛呢?

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

于 2013-08-13T15:19:17.123 回答