C# 异步接收,多个Xml数据接收,有时会导致多个根元素错误

C# 异步接收,多个Xml数据接收,有时会导致多个根元素错误,c#,xml-parsing,C#,Xml Parsing,以下是我当前使用的代码: if (bytesRead > 0) { if (recievedData.Trim().EndsWith("</CRootSystem>", stringComparison.Ordinal)) { if (state.packetCount > 0) { state.sb.Append(recievedData);

以下是我当前使用的代码:

if (bytesRead > 0)
{                    
    if (recievedData.Trim().EndsWith("</CRootSystem>", stringComparison.Ordinal))
    {
        if (state.packetCount > 0)
        {
            state.sb.Append(recievedData);
            state.totalSize += bytesRead;
            state.packetCount++;

            totalSize = state.totalSize;

            #region Insert into Packet
                Packet packet = new Packet(state.totalSize, state.packetCount);
                packetManager.Packets.Add(packet);
            #endregion

            parseXmlFeed(state.sb.ToString());

            #region Reset
                state.clear();
                recievedData = null;
            #endregion
        }
        else            
        {
            totalSize = bytesRead;

            #region Insert into Packet
                Packet packet = new Packet(state.totalSize, state.packetCount);
                packetManager.Packets.Add(packet);
            #endregion

            parseXmlFeed(recievedData);
        }
    }
    else
    {
        state.sb.Append(recievedData);
        state.totalSize += bytesRead;
        state.packetCount++;
    }
}
else //This part of code will never reached, because the connection and comm. with the server is never closed
{
    Display.Write("Nomore data Recieved.");
    receiveDone.Set();
}
if(字节读取>0)
{                    
if(receiveddata.Trim().EndsWith(“,stringComparison.Ordinal))
{
如果(state.packetCount>0)
{
陈述某人附加(收到数据);
state.totalSize+=字节读取;
state.packetCount++;
totalSize=state.totalSize;
#区域插入到数据包中
数据包=新数据包(state.totalSize,state.packetCount);
packetManager.Packets.Add(packet);
#端区
parseXmlFeed(state.sb.ToString());
#区域重置
state.clear();
receiveddata=null;
#端区
}
其他的
{
totalSize=字节读取;
#区域插入到数据包中
数据包=新数据包(state.totalSize,state.packetCount);
packetManager.Packets.Add(packet);
#端区
parseXmlFeed(receiveddata);
}
}
其他的
{
陈述某人附加(收到数据);
state.totalSize+=字节读取;
state.packetCount++;
}
}
else//这部分代码永远不会到达,因为与服务器的连接和通信永远不会关闭
{
显示。写入(“未收到更多数据”);
receiveDone.Set();
}
这段代码实际上非常有效。但有时我会在解析XMLparseXmlFeed时出错

我得到以下错误:

有多个根元素。第X行,位置Y

我知道这个错误的意思。我的xml数据中有不止一个根元素

但服务器从不发送错误的xml。服务器发送长数据(每个数据为8192字节)

示例:[8192字节]+[8192字节]+[176字节]

但从理论上讲,我不应该有一个有两个根的xml数据

我真的被困在这一点上了

我想我在添加数据或应该使用锁、互斥、半量或监视器时出错了

我应该在追加之前锁定数据吗

或者问题是,如何正确处理长数据

顺便说一句,我使用的是BeginReceive/EndReceive

将上述代码更改为:

    if (bytesRead > 0)
    {
        state.sb.Append(recievedData);
        state.totalSize += bytesRead;
        state.packetCount++;

        string data = state.sb.ToString();
        int dataSize = state.totalSize;

        if (data.TrimEnd().EndsWith("</CRootSystem>", StringComparison.Ordinal))
        {
            #region Insert into Packet
                Packet packet = new Packet(state.totalSize, state.packetCount);
                packetManager.Packets.Add(packet);
            #endregion

            parseXmlFeed(data);

            #region Reset
                state.clear();
                recievedData = null;
            #endregion
        }
        else
        {
            Display.Write("Waiting...");
        }
    }
    else 
    {
        Display.Write("No more data Recieved.");
        receiveDone.Set();
    }
if(字节读取>0)
{
陈述某人附加(收到数据);
state.totalSize+=字节读取;
state.packetCount++;
字符串数据=state.sb.ToString();
int dataSize=state.totalSize;
if(data.TrimEnd().EndsWith(“,StringComparison.Ordinal))
{
#区域插入到数据包中
数据包=新数据包(state.totalSize,state.packetCount);
packetManager.Packets.Add(packet);
#端区
parseXmlFeed(数据);
#区域重置
state.clear();
receiveddata=null;
#端区
}
其他的
{
显示。写入(“等待…”);
}
}
其他的
{
Display.Write(“不再接收数据”);
receiveDone.Set();
}

根据您的解释,我猜您在一次读取中收到多个
元素时会出现错误。8192字节的缓冲区大小不是由服务器设置的,而是由
TcpClient
的属性设置的(其默认值恰好是8192字节)。因此,如果服务器连续发送多批数据,您可能会在一个
BeginReceive
回调中收到它们

另一个问题:如果一个
文档的总大小恰好是8195字节,该怎么办?在这种情况下,第一次读取将为您提供
…(数据)…
EndsWith(“”
条件永远不会满足,因为关闭标记永远不会全部包含在
receiveddata

您的代码需要进行一些重要的修改。首先,为了正确性(但不是效率),您可以替换:

if (recievedData.Trim().EndsWith("</CRootSystem>", stringComparison.Ordinal))
与:


Regex rootRegex=new Regex(@“根据您的解释,我猜您在一次读取中收到多个
元素时会出现错误。8192字节的缓冲区大小不是由服务器设置的,而是由
TcpClient
的属性设置的(其默认值恰好是8192字节)。因此,如果服务器连续发送多批数据,您可能会在一次
BeginReceive
回调中收到它们

另一个问题:如果单个
文档的总大小恰好为8195字节,该怎么办?在这种情况下,第一次读取将为您提供
..(数据)…
EndsWith(“”
条件永远不会满足,因为关闭标记永远不会全部包含在
receiveddata

您的代码需要进行一些重要的返工。为了正确性(但不是效率),首先,您可以替换:

if (recievedData.Trim().EndsWith("</CRootSystem>", stringComparison.Ordinal))
与:


Regex rootRegex=newregex(@)您的客户端和服务器之间是否有某种形式的同步?具体来说,您的服务器是否在发送下一个
文档之前等待客户端的确认?如果没有,您是否可能在同一数据包中接收到两个文档?服务器来自另一个提供商,并且总是发送8192字节的数据由于缓冲区大小。服务器连续发送,您必须检查其长xml或单个xmlYes,但它是否只发送一个
文档然后停止?或者它可能稍后在同一连接上发送另一个文档?服务器不停发送。您必须检查EndRootTag或验证xml,以检查它是否确实是单个xmldata 8192。您是否有客户端和服务器之间的某种形式的同步?具体来说,服务器是否在发送下一个
文档之前等待客户端的确认?如果不是,是否可能
parseXmlFeed(data);
Regex rootRegex = new Regex(@"<CRootSystem.*?</CRootSystem>", RegexOptions.Singleline);
foreach (Match match in rootRegex.Matches(data))
    parseXmlFeed(match.Value);