Php APNS在不活动后无法传递消息

Php APNS在不活动后无法传递消息,php,apple-push-notifications,Php,Apple Push Notifications,我已经用PHP为APNS创建了一个客户机-服务器解决方案 “服务器”是一个持续运行的脚本,它等待连接并将内容复制到APN。这意味着它始终保持与APN的连接打开。我使用fwrite和stream上下文。这是接受传入连接的部件: if ($client = @stream_socket_accept($this->socket, -1)) { $this->writeLine("Received connection."); $this->inputBuffer =

我已经用PHP为APNS创建了一个客户机-服务器解决方案

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

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

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

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

}
它在while循环中运行,以便下一次迭代将inputBuffer的内容复制到APN,如下所示:

$writtenBytes = @fwrite($this->connectionAPNS, $this->inputBuffer, strlen($this->inputBuffer));
然后检查写入的字节,如:

if ($writtenBytes > 0) {

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

   return true;
}
现在,当连接处于空闲状态一段时间后,问题就出现了。第一次推送通知将返回写入APNS的字节数,例如“已将157字节复制到APNS”,这表示fwrite可以工作,但消息未传递

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

如果连接实际写入失败或者APN不接受,为什么要返回写入的字节

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

我在一个博客上找到了这段代码,在写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.

        }
     }
}
保持连接APN打开的“客户端”部分如下所示,并且在writtenBytes返回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;
        } 
    }

你的应用程序是发行版还是调试版?在每种情况下,您都必须与不同的web服务通信并使用不同的证书

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

在生产/休息模式下,与ssl://gateway.push.apple.com:2195


如果您与错误的服务进行通信,通知将自动删除。

这是生产。它只会在不活动后的第一次通知失败-所有后续通知都会正确到达。我很清楚沙箱和生产之间的区别——这不是这个问题的原因:)好的。我在你的资料中看不到,这是一个常见的陷阱。我会改进返回代码检查,比如:if(fwrite(…)==false){throw new Exception();}顺便问一下,你能保证你的设备是在线的吗。Apple有一个QoS组件,它只在设备离线时发送最新通知:fwrite返回写入的字节数。它不会返回false。如果是的话,我可以像平时一样重写。问题是,它返回为第一次通知编写的比特,然后在下一条消息中返回false-第一条消息随后丢失。设备处于联机状态。我只使用一个令牌和一个设备进行测试。是否尝试将写入缓冲区设置为0?当连接丢失时,字节可能会被缓冲。由于网络延迟,发送到苹果可能需要一段时间。同样的问题,你解决了吗?我在一个小时的不活动后重新连接。似乎已经解决了。是的,这应该是一个很好的解决办法。谢谢你的反馈。