C# 字符串未正确添加到自身。但是他能够比较 string returndata=“”; 字符串FullResponce=“”; bool receivereach=真; while(receiveveray==true) { byte[]inStream=新字节[clientSocket.ReceiveBufferSize]; serverStream.Read(inStream,0,inStream.Length); returndata=System.Text.Encoding.ASCII.GetString(流内); fullresponse+=返回数据; if(fullresponse.Contains(“”) { 再次接收=错误; } } LoadXml(FullResponce);

C# 字符串未正确添加到自身。但是他能够比较 string returndata=“”; 字符串FullResponce=“”; bool receivereach=真; while(receiveveray==true) { byte[]inStream=新字节[clientSocket.ReceiveBufferSize]; serverStream.Read(inStream,0,inStream.Length); returndata=System.Text.Encoding.ASCII.GetString(流内); fullresponse+=返回数据; if(fullresponse.Contains(“”) { 再次接收=错误; } } LoadXml(FullResponce);,c#,xml,string,loops,tcp,C#,Xml,String,Loops,Tcp,这是一个循环,用于继续检索数据,直到结束xml块(“”)包含在发送的所有数据包的FullResponce中。当代码运行时,在我的例子中经过大约5次循环后,(“”)最终包含在文本中 因此if语句运行并最终使receiveReach=false,从而中断循环,从而可以将fullResponse加载到xml中。当它试图加载xml时,会给我一个错误,即xml不完整,当我检查FullResponse文本时,它似乎丢失了除第一个数据包以外的所有内容(甚至丢失了“”,这很奇怪,因为循环中的if语句检测到了它)

这是一个循环,用于继续检索数据,直到结束xml块(
“”
)包含在发送的所有数据包的FullResponce中。当代码运行时,在我的例子中经过大约5次循环后,(
“”
)最终包含在文本中

因此if语句运行并最终使receiveReach=false,从而中断循环,从而可以将fullResponse加载到xml中。当它试图加载xml时,会给我一个错误,即xml不完整,当我检查FullResponse文本时,它似乎丢失了除第一个数据包以外的所有内容(甚至丢失了
“”
,这很奇怪,因为循环中的if语句检测到了它)

因为它缺少一半的xml,这就是为什么它会给出一个错误,但是为什么完整的响应不能正确地添加到自身中呢?代码fullresponse+=returndata似乎只运行一次,就是这样

另一件需要注意的事情是,当我在这个循环的开头设置一个断点,并手动检查所有代码,直到它尝试加载到xml中,它工作得非常好,FullResponse字符串是完整的,并且包含所有正确的数据

这就像当我让程序一步一步地运行时,它能够正确地将returndata添加到fullresponse,但是当没有断点并且调试正常时,它会给出错误


发生了什么以及如何修复此问题?

您的代码存在许多问题,但最大的问题(也是导致问题的原因)是您没有考虑到实际接收的字节数。这会导致字符串中存在空字符,然后一些组件会将空字符解释为字符串的结尾。(.NET字符串被计数,而不是NULL终止,但是仍然有很多代码,在字符串的中间没有期望一个空字符)。< /P> 您应该更改循环,使其看起来更像:

string returndata = "";
string FullResponce = "";

bool RecieveAgain = true;

while (RecieveAgain == true)
{
    byte[] inStream = new byte[clientSocket.ReceiveBufferSize]; 
    serverStream.Read(inStream, 0, inStream.Length);
    returndata = System.Text.Encoding.ASCII.GetString(inStream);
    FullResponce += returndata;

    if (FullResponce.Contains("< /Program>"))
    {
        RecieveAgain = false;
    }

}

xmlDoc.LoadXml(FullResponce);
注意:除了空字符的问题外,上述版本修复了原始情况下的另一个问题,即在循环中使用字符串连接。这样做会导致严重的性能和内存消耗问题;使用
StringBuilder
是在循环中连接文本的适当方法

注意:只要您确定您的XML只有ASCII字符,以上内容就可以了。但请注意,UTF8和UTF16现在很常见,从技术上讲,XML就是这些格式之一,而且有很多XML中包含非ASCII字符。您可能需要仔细检查XML的编码,并确保使用的是正确的编码

注意:在上述代码中,它使用流结束指示(即读取操作返回字节计数0)来终止循环。无论如何,你都应该检查一下。而且
StringBuilder
无法检查某些特定文本的包含情况,因此您以前的方法与
StringBuilder
的使用不兼容

现在,您可能会想“嘿,可能还有更多的数据!为什么不接受性能影响,并使用字符串连接和
Contains()
?”。好的,答案是:如果在XML结束后有可能出现更多的数据,那么您需要一种比查找close标记更可靠的方法来检测XML结束

Stream
对象无法知道它应该在XML末尾停止读取您的数据,因此最后一次读取操作(带有XML的最终关闭标记的操作)可以(也可能会)包含XML后面的部分数据

这意味着你会有两个问题:

  • 您的XML被额外的数据污染了
  • 这些额外的数据(可能对以后发生的事情很重要)已经被读取,并且不会提供给需要它的代码
  • 解决这个问题的一种方法是在数据流中的XML前面加一个字节计数,这样循环就知道在停止之前要读取多少字节。另一种方法可能是将XML转换为二进制文件,然后再转换为base64(可能先压缩二进制文件),然后用一些您知道对base64数据无效的字符(例如空格、换行符、制表符等)分隔base64数据

    无论您如何处理它,您都可以通过某种机制而不是XML本身的最终关闭标记来知道XML的结尾,因此仍然可以使用
    StringBuilder
    ,并且不必在字符串中搜索该关闭标记


    我将提供关于后一方面的更多细节,但您在问题中没有提供足够的信息。如果您在这方面需要帮助,请发布新问题,并确保提供适当的详细信息。有关如何更好地表达问题的建议,请参阅和。

    您的代码存在许多问题,但最大的问题(也是导致问题的原因)是您没有考虑到实际接收的字节数。这会导致字符串中存在空字符,然后一些组件会将空字符解释为字符串的结尾。(.NET字符串被计数,而不是NULL终止,但是仍然有很多代码,在字符串的中间没有期望一个空字符)。< /P> 您应该更改循环,使其看起来更像这样:

    StringBuilder fullResponse = new StringBuilder(); byte[] buffer = new byte[clientSocket.ReceiveBufferSize]; int bytesRead; while ((bytesRead = serverStream.Read(buffer, 0, buffer.Length)) > 0) { string textRead = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead); fullResponse.Append(textRead); } xmlDoc.LoadXml(fullResponse.ToString());