如何在自定义TCP客户端/服务器之间正确传递XML字符串?

时间:2009-09-13 18:38:36

标签: .net c++ xml tcp

我正在开发一个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#。

非常感谢任何帮助!

5 个答案:

答案 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)

我能想到三种方式:

  • 描述带外长度: 这可能有点像HTTP header:CR在ascii中删除长度,然后计算所有后续字节 长度。
  • Null终止字符串。 Null char是独一无二的。
  • CR或LF终止节点,基于行的协议可以读取XML。

如其他地方所述,请确保您的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