【问题标题】:How do I receive push notifications with Indy?如何使用 Indy 接收推送通知?
【发布时间】:2013-05-04 00:12:10
【问题描述】:

我有一个使用 RESTful Web 服务的设备,我使用了它的请求/响应功能,通过 HTTP GET 向它发送一个命令,它以适当的 XML 响应。

我现在需要使用设备的 pus 通知。我尝试了与上面相同的方法,即我为TIdHTTP.Get 过程提供了相关的HTTP URL 和用于放置响应的流,但这似乎不起作用。对Get 的呼叫没有回来。这对我来说很有意义,因为通过推送通知,您正在打开设备和程序之间的 HTTP 通信流,并且此连接将保持打开状态以进行流式传输,直到关闭。

我的问题是,如果Get 方法没有返回,我不知道如何从流中获取 XML。就好像程序挂了一样。我试图通过 GET 与设备进行通信并将流的读取放入一个线程中,以便它可以自行继续,然后我的主应用程序可以检查生成的 XML,但这也不起作用。

我想知道我是否过于复杂了,是否有一个简单的解决方案。当我简单地发送请求并得到响应时,它工作正常;这只是我无法工作的推送流。

如果我在 Internet Explorer 中使用 URL,我可以看到返回的 XML 以及持续运行的“忙碌”徽标,表明流已打开。

我已经通过我的浏览器 Firefox Mozilla 20.0.1 运行了该命令,并查看了 wireshark 为推送请求和响应捕获的内容。 HTTP部分如下所示:

GET /elite/notifications/stream?resume=2013-05-06T00:00:00Z HTTP/1.1 
Host: 192.168.10.10 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 
Accept-Language: en-US,en;q=0.5 
Accept-Encoding: gzip, deflate 
Connection: keep-alive

我在 Delphi 中尝试做的请求如下:

if fEventStream = nil then
  fEventStream := TStringStream.Create('');
try
  TapItem.fHTTP.Get(TapItem.I2IReaderIP+'/elite/notifications/stream?resume=2013-05-01T00:00:00Z',fEventStream);
  TapItem.fEventXML := fEventStream.ReadString(fEventStream.Size);
except
  on e:exception do begin
    ShowMessage(e.message)
  end;
end;

我也试过 TidTCPConnection

  fTCPConn.IOHandler.Writeln(TapItem.I2IReaderIP+I2I_PUSH_EVENT+'2013-05-01T00:00:00Z');
  While not Terminated do begin
    XMLString := XMLString + fTCPConn.IOHandler.Readln;
  end;

我们将不胜感激。

解决方案


在我的情况下,只需将 GET 关键字添加到调用的开头即可。我假设 TCP 连接组件需要知道您希望执行的操作(即 GET PUT 等),它无法读懂我的想法,这是有道理的

fTCPConn.IOHandler.Writeln('GET ' + TapItem.I2IReaderIP+I2I_PUSH_EVENT+'2013-05-01T00:00:00Z');
While not Terminated do begin
  XMLString := XMLString + fTCPConn.IOHandler.Readln;
end;

【问题讨论】:

  • 提示:在 Stackoverflow 上,您可以添加您的解决方案作为答案(并接受它)

标签: xml web-services delphi indy


【解决方案1】:

TIdHTTP 目前不支持服务器端推送(即便如此,也有多种方式可以实现服务器端推送——您的 REST 服务使用哪一种?)。您必须切换到TIdTCPClient,手动格式化和发送 HTTP 请求,然后使用计时器或线程在推送的响应到达时根据需要读取和解析它们。

【讨论】:

  • 我不认为你能提供一个简单的例子来说明如何做到这一点?我现在已经更新了我的代码以使用 TidTCPClient 代替,经过一些摆弄后得到了某种形式的响应,但它是 HTML。看起来像文档标题信息。没有返回 XML。找不到如何做到这一点的好例子。谢谢
  • 我建议您使用数据包嗅探器(例如 Wireshark 或 Fiddler)来查看 IE 如何请求 URL,然后在 Indy 中复制这些请求值。特别是User-Agent,因为一些服务器为不同类型的客户端发送不同的内容,当涉及到服务器推送时,网络服务器很可能对不同类型的网络浏览器使用不同类型的推送,因为没有标准化的格式推动每个人都同意呢。如果您使用嗅探器捕获的推送示例更新您的问题,我可以向您展示如何使用 TIdTCPClient 复制它。
  • 嗨。不完全确定您在寻找什么。我已经通过浏览器运行了该命令,并查看了 wireshark 为推送请求捕获的内容。 HTTP 部分如下所示: GET /elite/notifications/stream?resume=2013-05-06T00:00:00Z HTTP/1.1 Host: 192.168.10.10 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv: 20.0) Gecko/20100101 Firefox/20.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-US,en; q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive
  • 我还可以在 Wireshark 中看到返回的相关 XML。我的问题是如何在 Delphi 中实现它。我在 Delphi 中的代码是 try fTCPConn.IOHandler.Writeln(TapItem.I2IReaderIP+I2I_PUSH_EVENT+'2013-05-01T00:00:00Z');虽然没有终止,但开始 XMLString := XMLString + fTCPConn.IOHandler.Readln;结尾;最后 ShowMessage(XMLString);结束;
  • 我在 Delphi 中得到的回复是:ttp://www.w3.org/TR/html4/frameset.dtd" rel="nofollow" target="_blank">w3.org/TR/html4/frameset.dtd"> EPFCA01423-FC00110000000105 [v1.02.005] '
【解决方案2】:

Indy 10.6 主干中的 HTTP 客户端 (TIdHTTP) 现在也支持“服务器推送”,如果服务器发送 multipart/... 响应:

New TIdHTTP hoNoReadMultipartMIME flag

新的 hoNoReadMultipartMIME 标志已添加到 TIdHTTP.HTTPOptions 属性。此标志的目的是指定 TIdHTTP 是否应该读取“multipart/...”的正文内容 响应,例如“multipart/x-mixed-replace”或 “multipart/byteranges”,进入目标 TStream 或立即退出 并让调用者手动读取内容。

由于实现服务器推送的方法有很多种,因此这个答案对于给定的服务器可能或多或少有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 2018-08-24
    • 2021-09-03
    • 2019-02-18
    相关资源
    最近更新 更多