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);
这是一个循环,用于继续检索数据,直到结束xml块("< /Program>"
)包含在组合发送的所有数据包的FullResponce中。运行代码时,在我的情况下大约5个循环后,("< /Program>"
)最终包含在文本中。
因此if语句运行并最终使RecieveAgain = false,从而打破循环,因此可以将FullResponce加载到xml中。当它试图加载xml时,它给我一个错误,即xml不完整,当我检查FullResponce文本时,它似乎丢失了除第一个数据包之外的所有内容(甚至错过了"< /Program>"
,是奇怪的,因为循环中的if语句检测到它)。
因为它缺少xml的一半,这就是它给出错误的原因,但为什么完全响应没有正确添加到自身?代码FullResponce + = returndata似乎只运行一次,就是这样。
另外需要注意的是,当我在此循环的开头设置断点,并手动浏览所有代码,直到它尝试加载到xml中,它完全正常,并且FullResponce字符串已满并且完成所有正确的数据。
就像我一步一步运行程序一样,它可以正确地将returnsndata添加到FullResponce,但是当没有断点并且正常调试时,它会给出错误。
发生了什么,我该如何解决这个问题?
答案 0 :(得分:3)
您的代码存在许多问题,但最大的问题(以及导致问题的问题)是您未能考虑实际接收的字节数。这会导致字符串中存在空字符,然后由某些组件将其解释为字符串的结尾。 (.NET字符串是计数的,不是以空值终止的,但仍然有很多代码在字符串中间没有预期空字符)。
您应该将循环更改为更像这样:
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());
注意:除了空字符问题之外,上述版本修复了原始情况下的另一个问题,即您在循环中使用字符串连接。这样做会导致严重的性能和内存消耗问题;使用StringBuilder
是在循环中连接文本的适当方法。
注意:只要您确定您的XML只有ASCII字符,上面就可以了。但请注意,UTF8和UTF16现在很常见,XML在技术上是其中一种格式,并且其中有很多XML,其中包含非ASCII字符。您可能需要仔细检查XML的编码,并确保在此处使用正确的编码。
注意:在上面的代码中,它使用流结束指示(即读操作返回字节数为0)来终止循环。无论如何你绝对应该检查这个。并且StringBuilder
无法检查某些特定文字的遏制情况,因此您之前的方法与StringBuilder
的使用不兼容。
现在,您可能正在考虑自己&#34;嘿,但可能会有更多数据!为什么不接受性能命中并使用字符串连接Contains()
?&#34;。那么,答案就是:如果在XML结束后可以存在更多数据,那么您需要一种更可靠的方法来检测XML的结尾,而不是查找关闭标记。
Stream
对象无法知道它应该在XML的末尾停止读取数据,因此最后的读取操作 - 具有XML的最终关闭标记的操作 - 可以(可能会)包含XML之后的一部分数据。
这意味着你有两个问题:
解决此问题的一种方法是在数据流中的XML之前加上字节数,以便循环知道在停止之前要读取的字节数。另一种方法可能是将XML转换为二进制,然后转换为base64(可能首先压缩二进制文件),然后使用您知道对base64数据无效的某些字符(例如空格,换行符,制表符)分隔base64数据等等。)。
无论你如何解决它,你都会通过XML本身的最终关闭标记之外的某种机制来了解XML的结束,因此仍然可以使用StringBuilder
并且不会有搜索该字符串以查找该关闭标记。
我会提供有关后一方面的更多详细信息,但您尚未在问题中提供足够的信息。如果您需要具体的帮助,请发布一个新问题,并确保提供相应的详细信息。有关如何更好地提出问题的建议,请参阅https://stackoverflow.com/help/mcve和https://stackoverflow.com/help/how-to-ask。