如何有效地定义基于XML的文本协议的传输结束?

时间:2012-04-18 08:37:42

标签: xml tcp xml-parsing xmpp protocols

我想开发一个基于XML的文本协议,并通过TCP / IP套接字传输。 假设我有一个简单的请求/响应机制要通过持久性发送 客户端和服务器之间的TCP / IP连接如下:

<?xml version="1.0" encoding="UTF-8"?>
<request id="1" command="get.answer">
    <value type="string">Answer to the Ultimate Question of Life, the Universe, and Everything</value>
</request>

<?xml version="1.0" encoding="UTF-8"?>
<response id="1" command="get.answer">
    <value type="int32">42</value>
</response>

每一方何时应该开始处理传入的数据,换句话说 什么时候服务器知道传入的客户端数据是完全传输的 并且可以处理以创建响应?

当然,我对该主题进行了一些研究: 我发现this答案基于HTTP示例指向了正确的方向: 因此,在XML消息之上使用一种“传输协议”肯定会有所帮助。

但我也看了一下纯粹基于XML的XMPP协议,该协议不使用任何协议 像HTTP一样的“传输协议”至少就我所见。

来自RFC 6120的“2.4。结构化数据”,其内容为:

  

XMPP中的基本协议数据单元不是XML流(其中   简单地提供点对点通信的传输)但是   XML“节”,它本质上是发送的XML片段   在一条小溪上。节的根元素包括路由   属性(例如“from”和“to”地址)和子节点   节的元素包含有效载荷以传递给预期的   收件人。

因此,他们通过TCP / IP发送基本上小的XML块,而没有'传输协议' 我的wireshark痕迹我可以看到,也没有特殊的End-Of-Transmission角色 在每个XML节的结尾,像两次\ r \ n或类似的东西。 那么他们如何知道消息的结束(节)?

4 个答案:

答案 0 :(得分:2)

实际上,XMPP使用XML stream来传输数据。您所指的数据单元是单个消息的实际交换,但它们都包含在XML流中,该XML流定义了XMPP会话的通信的起始和终点。

这将是传输结束发生的地方,如在所有传输结束时。在该流中,有3种已定义的数据包类型(IQ,消息和状态),它们指示各个消息的开始和结束(对于客户端到服务器通信)。

虽然基本情况是通过TCP连接完成的,但也有扩展支持不同的有线协议,例如HTTP,这对于允许XMPP通过防火墙非常有用。

如果你想做类似的事情,那么你可以采用相同的方法,即在建立和删除连接时开始和结束XML流。然后,您只需定义各个消息类型,以便您的端点知道什么构成完整的消息。

或者您可以使用XMPP,它似乎完全适合您的用例。

答案 1 :(得分:0)

如@Robin所说,XMPP有一个基于XML流的传输。它还可以使用HTTP作为BOSH的传输。

在第二个(HTTP)情况下,事情很简单。 Strophe例如,使用BOSH的js库,请求 本质上是HTTP请求,因此具有Content-Length。它看起来像这样:

POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 240

<body rid='1573741825'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='bind_1'
      type='set'
      xmlns='jabber:client'>
    <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
      <resource>httpclient</resource>
    </bind>
  </iq>
</body>

在第一种情况下(XML流)虽然情况有所不同。我使用的一个性能良好,存在时间长且经过测试的python库TwistedExpat XML parser上使用了一个python包装器。解析器是一个快速,无验证的解析器,它抛出有用的事件,例如指示“根”元素的开始或结束。然后,这些元素在接收时逐个解析。

答案 2 :(得分:0)

正如here中提到的,主要有两种方法:在标题中有分隔符或长度。您的分隔符可能只是开始标记的结尾,这就是XMPP正在做的事情。这意味着只要您的XML消息包含在正确开始和结束的标记中,您就可以开始使用了。如果您希望对收到的数据块进行某种验证,那么您需要做的是确保所有标记都有结束。大多数解析器包都会为您执行此操作。如果你传递一个不可解析的包,他们会给你一个例外。如果你想编写自己的解析器,那么你需要更多地研究解析器而不是转移/ XML协议。

答案 3 :(得分:0)

XMPP端点必须解析XML。通过这样做,它知道结束的时间,因为只允许1个文档(顶级)元素(我不确定它们是否可能在XML处理器指令之前)

<?xml version="1.0" encoding="UTF-8"?>
<request id="1" command="get.answer">
    <value type="string">Answer to the Ultimate Question of Life, the Universe, and Everything</value>
</request>

这是自我分隔的,因为一旦你解析了<request标记,你知道当你点击匹配的</request>时,这个XML文档会结束。

(就个人而言,我会在下面的协议级别放置一个成帧协议,而不是在一个(TCP)流的顶部填充原始xml,也许只是在每个带有4字节大字节长度字段的消息之前。)