【发布时间】: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