我正在开发一个C ++客户端/服务器项目,其中XML字符串通过TCP / IP连接传递。我的问题是关于指示已收到完整字符串的正确方法。我考虑的是空终止字符串或首先发送XML字符串的长度,因此客户端/服务器可以判断何时收到完整的字符串。
客户端可以发送GET / SET命令,服务器可以回复,也可以发送连续的结果流。例如:客户端发送<GET ID="DATA1" />
和服务器回复<ID="DATA1" VAL="..." />
或者服务器可以发送连续流:
<ID="DATA1" VAL="..." />
<ID="DATA2" VAL="..." />
<ID="DATA3" VAL="..." />
<ID="DATA4" VAL="..." />
在这种情况下,客户端可能会收到一个Read:
<ID="DATA1" VAL="..." /><ID="DATA2" VAL="..." />
或者如果发送了大量数据,可能需要多次读取才能读取整个字符串。
使用空终止字符似乎有点简单(如果字符串是unicode会中断?)并且发送长度值似乎也很尴尬:
20<ID="DATA1" VAL="1" />
或<length=20><ID="DATA1" VAL="1" />
HTML文件的TX / RX必须已经解决,我似乎无法弄明白。
我正在为服务器使用MFC C ++(遗留代码),为客户端使用.Net C ++ / CLI或C#。
非常感谢任何帮助!
答案 0 :(得分:5)
您的示例实际上并不是格式良好的XML,这可能是您问题的一部分。如果您遇到使用XML的麻烦,您也可以使用格式良好的XML,它具有节点终止的规则,即:
<data id="DATA1" val="..." />
或
然后,您可以为流使用SAX解析器,它将为您提供事件,因为节点和属性都会被解析。
然后我会实现你的两种命令:
// individual commands
<get id="data_1"/>
// multiple commands
<multi>
<data id="DATA1"/>
<data id="DATA2"/>
...
</multi>
答案 1 :(得分:1)
我看到两个很有意义的选项,我以前用过:
1-只需发送它,不要终止XML。如果XML有效,它将只有一个根节点。您不必终止它,因为客户端可以解析它,直到它发现它有一个完整的XML文件。
2-使用“Pascal”样式字符串。我发现这很容易,因为读取可以一次完成,并且所有其他问题都不存在。基本上,在前面加上“字符串”文档,该整数是要发送的字节数。我特别是在处理TCP时这样做,因为我可以同时取出所谓的“数据包”或完整数据组。
答案 2 :(得分:0)
使用零字节是正确的方法。它应该(至少afaik)不会破坏任何关于unicode或其他编码的东西,并且给你的灵活性比任何长度的字节/长都要多。
答案 3 :(得分:0)
我能想到三种方式:
如其他地方所述,请确保您的XML符合标准,以便可以换出任何一方,然后不必调整旧代码以符合。
答案 4 :(得分:0)
我喜欢简单的CRLF分隔的想法,似乎最简单。从提供的链接,这将工作? (CRLF ==两个字节1013)
发送:
<GET ID="DATA1" />CRLF
答复:
<ID="DATA1" VAL="3" />CRLF
<ID="DATA1" VAL="2" />CRLF
<ID="DATA1" VAL="1" />CRLF
...
如上所述,可能会出现多行的XML回复。这可能会导致每行CRLF出现问题,而不是响应的结束? CRLF不能自然地出现在多行XML字符串中吗?
答复:
<multi>CRLF
<data id="DATA1"/>CRLF
<data id="DATA2"/>CRLF
</multi>CRLF