用Workerman实现 苹果推送服务, 进驻内存运行, 雏形
<?php
use Workerman\Worker;
use \Workerman\Lib\Timer;
use \Workerman\Connection\ApnsTcpConnection;
use \Lib\Db;
require_once '../Workerman/Autoloader.php';
function loadList($conn)
{
//查数据库
$rows = Db::instance('apns')->query("SELECT * FROM `list` WHERE status=0 limit 100");
echo "\n本次处理".count($rows)."条";
//开始计时
$s_time = microtime(true);
foreach ($rows as $row) {
$deviceToken = $row['token'];
// $deviceToken = '16cc41dd93e011d1b10506c9ce79bbde073a884cb93cabecdf2a5a45e2eeb80d';
//创建结构
$body['aps'] = array(
'badge' => $row['badge'],
'alert' => $row['alert'].date("H:i:s"),
'sound' => 'default',
);
//json编码
$payload = json_encode($body,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
/* //2代 组装
$itemData = pack('H*',$deviceToken).$payload.pack('NNC',0,864000,10);
$item = pack('Cn',0, strlen($itemData)).$itemData;
$msg = chr(2). pack('N',strlen($item)).$item;
*/
//0代 组装
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
$a = $conn->send($msg, true);
if ($a) {
//发送成功 标记数据库
// Db::instance('apns')->query("UPDATE `list` SET `status`=1 WHERE id={$row['id']}");
}else{
}
// echo "\n".date("Y-m-d H:i:s")." {$row['id']}:{$row['token']} 发送".($a?'成功':'失败');
}
$t = (microtime(true)-$s_time)*1000;
echo "\n用时:{$t}毫秒";
//x秒后执行一次
Timer::add(3.0, 'loadList', [$conn], false);
}
$task = new Worker();
// 进程启动时异步建立一个到www.baidu.com连接对象,并发送数据获取数据
$task->onWorkerStart = function($task)
{
//SSL连接
// $url = 'ssl://gateway.sandbox.push.apple.com:2195';
$url = 'ssl://gateway.push.apple.com:2195';
$local_cert = "./dis.ck.pem";
$passphrase = "密码";
//打开与苹果推送服务器的连接
$con = new ApnsTcpConnection($url,$local_cert, $passphrase);
$con->onConnect = function($conn)
{
echo "\nconnect success";
loadList($conn);
// $con->send("GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: keep-alive\r\n\r\n");
};
$con->onMessage = function($con, $data)
{
echo "\nonMessage:".strlen($data)." ";
$arr = unpack("Ccmd/Cstatus/Next", $data);
$codes = [
0 => '没有错误发生',
1 => '处理错误',
2 => '缺失DiviceToken',
3 => '缺少topic',
4 => '缺少荷载数据',
5 => '无效的token大小',
6 => '无效的topic大小',
7 => '无效的荷载数据大小',
8 => '无效的token',
10 => '连接关闭',
255 => '未知错误',
];
if ($codes[$arr['status']]) {
echo $arr['status']." ".$codes[$arr['status']];
}else{
print_r($arr);
}
};
$con->onClose = function($con)
{
echo "\nconnection closed";
};
$con->onError = function($con, $code, $msg)
{
echo "\nError code:$code msg:$msg";
};
$con->connect();
};
// 运行worker
Worker::runAll();