【问题标题】:APNS fails to deliver message after inactivityAPNS 在不活动后无法传递消息
【发布时间】:2015-11-22 22:16:00
【问题描述】:

我已经在 PHP 中为 APNS 创建了客户端-服务器解决方案。

“服务器”是一个持续运行的脚本,它等待连接并将内容复制到 APNS。这意味着它始终保持与 APNS 的连接打开。我使用 fwrite 和流上下文。这是接受传入连接的部分:

if ($client = @stream_socket_accept($this->socket, -1)) {

   $this->writeLine("Received connection.");

   $this->inputBuffer = stream_get_contents($client);

}

它在一个while循环中运行,因此下一次迭代将inputBuffer的内容复制到APNS:

$writtenBytes = @fwrite($this->connectionAPNS, $this->inputBuffer, strlen($this->inputBuffer));

然后我检查写成这样的字节:

if ($writtenBytes > 0) {

$this->writeLine("Copied $writtenBytes bytes to APNS.");

   return true;
}

现在,当连接闲置一段时间后,就会出现问题。第一个推送通知将返回写入 APNS 的字节数 - 例如“Copied 157 bytes to APNS.”,表示 fwrite 有效,但消息未送达。

然后下一个通知返回写入的 0 个字节,自动重新连接(我的脚本的一部分)并写入失败的字节 - 然后它就可以工作了。

如果连接实际上无法写入或 APNS 不接受它们,为什么我会返回写入的字节?

我使用增强的通知格式并检查返回的错误,但似乎没有错误。

我为此使用了这段代码,我在博客上找到了该代码,我在写入 APNS 后将连接句柄传递给函数:

function checkAppleErrorResponse($fp)
{
    $apple_error_response = fread($fp, 6);

    if ($apple_error_response) {

        error_response = unpack('Ccommand/Cstatus_code/Nidentifier', $apple_error_response);

        if ($error_response['status_code'] == '0') {
            $error_response['status_code'] = '0-No errors encountered';
        } else {
            // Here is some fancy if/else error handling, but I never end in this else , so I excluded it.

        }
     }
}

保持连接 APNS 打开的“客户端”部分如下所示,每当 writeBytes 返回 0(错误)或脚本首次加载时都会调用它:

function connectToAPNS()
    {

        $ctx = stream_context_create();
        stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certpath);
        stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase);


        // Open a connection to the APNS server
        $error = "";
        $errno = 0;
        $this->connectionAPNS = stream_socket_client(
            'ssl://gateway.push.apple.com:2195',
            $errno,
            $error,
            60,
            STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT,
            $ctx
        );

        if ($this->connectionAPNS) {
            stream_set_blocking($this->connectionAPNS, 0);
            $this->writeLine("Connected to APNS!");

            return true;
        } 
    }

【问题讨论】:

  • 同样的问题,你解决了吗?
  • 我在闲置一个小时后重新连接。似乎已经解决了。
  • 是的,这应该是一个很好的解决方法。感谢您的反馈。

标签: php apple-push-notifications


【解决方案1】:

您的应用是发布版还是调试版?在每种情况下,您都必须与不同的网络服务通信并使用不同的证书。

在沙盒/调试模式下与 ssl://gateway.sandbox.push.apple.com:2195 通信

在生产/发布模式下与 ssl://gateway.push.apple.com:2195

通信

如果您与错误的服务通信,通知将被静默删除。

【讨论】:

  • 这是生产。它仅在不活动后的第一次通知时失败 - 所有以后的通知都会正确到达。我很清楚沙盒和生产之间的区别 - 这不是这个问题的原因:)
  • 好的。我在您的来源中看不到它,这是一个常见的陷阱。我会改进返回代码检查,例如: if (fwrite(...) === false) { throw new Exception(); } 顺便提一句。你能确保你的设备在线吗? Apple 有一个 QoS 组件,仅在设备离线时提供最新通知:developer.apple.com/library/ios/documentation/…
  • fwrite 返回写入的字节数。它不会返回错误。如果是这样,我可以像往常一样重写。问题是它返回为第一个通知编写的叮咬,然后在下一条消息上返回 false - 然后第一条消息丢失。
  • 设备在线。我只使用一个令牌和一个设备进行测试。
  • 您是否尝试将写入缓冲区设置为 0? php.net/manual/en/function.stream-set-write-buffer.php 可能在连接丢失时缓冲字节。由于网络延迟,发送到 Apple 可能需要一段时间。
猜你喜欢
  • 2018-12-28
  • 2010-10-05
  • 2018-08-25
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多