【问题标题】:Detecting if stream_socket is valid检测stream_socket是否有效
【发布时间】:2015-07-21 19:52:21
【问题描述】:

我有一个无限期运行的类似 PHP 服务器的脚本。它使用 PHP 中的 stream_socket_client 对象连接到 APNS(Apple 推送通知服务)。

问题是,虽然这在大多数情况下都有效,但当我想发送推送通知时,我无法弄清楚如何验证与 APNS 的连接是否可用。该脚本接收传入连接并将内容复制到 APNS。

当它不起作用时,脚本重新连接(stream_copy_to_stream 的返回值为 0 on 0 bytes 写入,这会触发重新连接)然后下一个传入的令牌会成功,但它会记录以下内容当然不会传递消息:

PHP Warning:  stream_copy_to_stream(): SSL: An established connection was 
aborted by the software in your host machine.

有什么方法可以检测到上述情况,从而在尝试写入套接字之前重新连接到 APNS。

在尝试复制到 APNS 之前执行此操作:

if (!$socketObject) { 
    // reconnect
}

不起作用,因为对象仍然存在(var_dump 将打印描述)。那么如何检查连接是否仍然打开?

向套接字写入任何不是有效令牌和有效负载的内容都会导致 APNS 断开连接。

执行写入的代码如下所示:

  function writeToAPNS($client) {
        return stream_copy_to_stream ( $client, $this->connectionAPNS );
    }

其中$client 是从stream_socket_accept ( $this->socket, -1 ) 返回的,$this->socket 是一个变量,其中包含侦听传入连接的本地套接字对象。 -1 表示等待传入连接时没有超时。当它工作时,这个函数返回写入的字节数。失败时返回 0。

$this->connectionAPNS是连接APNS时stream_socket_client返回的对象。这是我在执行stream_copy_to_stream 函数之前要检查的有效性。

所以基本上我想检测$this->connectionAPNS 是否有效

我尝试转储连接对象的元数据,但它没有说明有效性,只有当它超时、协议类型等时才说明。

【问题讨论】:

  • 你错过了展示可重现的东西。
  • 那我再添加一些代码。等等。

标签: php sockets stream


【解决方案1】:

您在stream_socket_client 官方文档中看到此说明吗?

即使远程主机无法访问,UDP 套接字有时也似乎已打开且没有错误。 只有当您从套接字读取或写入数据时,该错误才会变得明显。这样做的原因是因为 UDP 是一个“无连接”协议,这意味着操作系统不会尝试为套接字建立链接,直到它真正需要发送或接收数据。

请在您的连接上尝试这种方法stream_get_meta_data 以尝试检测差异。我现在无法测试它,但它可能会对你有所帮助。尤其是 timed_out 属性。

另一个至少静音错误消息的选项,因为您正在处理它们,是在 stream_socket_client 上设置适当的 errno

【讨论】:

  • 我做了,但我没有打开 UDP 连接,所以这不适用。 APNS 不在 UDP 协议上运行。
  • @nickdnk 如果没有,如果对您有用,我将删除我的答案。
  • UDP 部分不是。剩下的就是。我尝试使用stream_get_meta_data,但它似乎没有告诉我连接是否有效,只有类型,如果超时等。
  • 问题是你的 $stream 不能在一段时间后变为空。您只能在流创建后立即以这种方式执行检查。所以我现在看到的避免这种情况的唯一方法是让你每次都创建一个新客户端。 (别忘了关闭旧的)
  • 我想我可以将传入的连接存储在一个变量中而不是直接复制它,然后如果写入失败,重新连接并在重新连接后再次写入传入的连接。
【解决方案2】:

嗯,正如 M.K. 所解释的,这就是 UDP 的工作原理。顺便说一句,您的代码有效。你的问题是警告,通过在你的 write 函数中添加一个 @ 很容易摆脱它。 您的代码将如下所示:

 function writeToAPNS($client) {
    return @stream_copy_to_stream ( $client, $this->connectionAPNS );
}

【讨论】:

  • 但它是一个 TCP 套接字!
  • 我将在 Java 上重建这个解决方案,并使其成为多线程的,这样它就可以一次处理许多请求。但到目前为止,这个 PHP 解决方案运行良好。我在闲置 1 小时后重新连接解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
相关资源
最近更新 更多