runtime.runloopiOS常用面试常见问题

IOS APNS和VOIP 实现推送(本质)

2021-04-03  本文已影响0人  刃之剑

iOS 的推送本质

iOS 在系统级别有一个推送服务程序使用 5223 端口。使用这个端口的协议源于 Jabber 后来发展为 XMPP ,被用于 Gtalk 等 IM 软件中。

所以, iOS 的推送,可以不严谨的理解为:
苹果服务器朝手机后台挂的一个 IM 服务程序发送的消息。
然后,系统根据该 IM 消息识别告诉哪个 Apps 具体发生了什么事。
然后,系统分别通知这些 Apps 。

iOS 的推送:就是 Apple 官方的 APNs (Apple Push Notification service)。Android 的推送:Google 官方的是 GCM (Google Cloud Messaging)。

本质上,APNs 与 GCM 是类似的技术实现原理:即系统层有一个常驻的 TCP 长连接,一直保持的长连接,即使手机休眠的时候也在保持的长连接。

这里对于大部分人来说,最不理解的就是,休眠时候都保持在那里的 TCP 长连接,不会耗电很厉害么?答案是:不会。这是手机的设计来做到的。TCP长连接有个心跳的时间,在国外可以很长比如30分钟,在国内则因为网络环境复杂一般10分钟。客户端发起的心跳,会短暂地消耗手机电能,但在这个心跳间隔期间,则消耗电能是很少的。当在心跳期间服务器端有推送信息过来时,客户端可以收到并做处理。

再说 APNs 的设计成功处。

iOS 为了真正地为用户体验负责,不允许应用在后台活动。有了这个限制,但是对于终端设备,应用又是有必要“通知”到达用户的,随时与用户主动沟通起来的(典型的如聊天应用)。

这就是 APNs 的逻辑所在:iOS 自己做个长驻后台保持连接。所有应用,有必要(申请)并且被允许(用户可以改设置)的话,可以通过 APNs 中转到达用户。

feedback接口是一个后验的接口

那么既然失效的device-token是导致发送变慢的主要原因,那么开发者朋友们肯定会想,能不能提前判断出失效的device-token,直接从发送列表中剔除掉这些失效的token。其实APNs是提供这样的feedback接口的,调用这个接口会得到一批失效的device-token列表。那么是不是在一次发送之前去调用一下这个接口,获取到无效的device-token,在发送的过程中剔除掉这些无效的device-token就能加快发送速度呢? 其实不然,因为feedback接口是一个后验的接口,即只有一次推送任务结束之后,APNs才会把该次失效的device-token更新到feedback接口的返回结果里面。如果你在一次推送任务前调用feedback接口,那么得到的失效device-token是基于上一次推送任务的结果的,两次推送任务之间发生的失效的device-token,是无法提前获取到的,只能等当次推送任务结束之后,才可以去获取新的失效token列表。

具体来说:

APNS就不多说了.这里的APNS主要是实现像支付宝收款到账的那个信息的(Extension 以及 静默推送(无alert字段即可))

出去使用第三方推送上传证书到第三方,such as 极光推送,友盟推送,信鸽推送,个推等.
也有用于即时通讯的比如环信和融云,网易,腾讯等等.

voip:

   **基于IP的语音传输**(英语:Voice over Internet Protocol,缩写为**VoIP**)
   是一种语音通话技术,经由[网际协议](IP)来达成语音通话与[多媒体]会议,
也就是经由[互联网]来进行通信。
   其他非正式的名称有IP电话(IP telephony)、互联网电话(Internet telephony)、宽带电话(broadband telephony)以及宽带电话服务(broadband phone service)。
   VoIP可用于包括VoIP电话、[智能手机]、个人计算机在内的诸多互联网接入设备,通过[蜂窝网络]、[Wi-Fi]进行通话及发送[短信]。

如果不想把证书上传到第三方平台可以自己制作证书进行推送测试:
可以自己制作证书,用smartPush,或者python,php脚本进行推送模拟测试.

apns证书制作

1. 打开“钥匙串”程序,(证书助理->从证书颁发机构请求证书),只填邮箱和常用名称,ca不用填,然后保存.certSigningRequest文件到磁盘。
2. 在iOS Dev Center 点击App IDs进入App ID列表。
3.为 App 开启 Push Notification 功能。(推送证书分为两个版本,一个是Development版,一个是Production版,分别对应开发证书和发布证书。)
4.上传刚才生成的.certSigningRequest文件,生成aps_development.cer推送证书,双击安装。
5. 打开“钥匙串”程序,(选择登录与我的证书选项后)找到IOS Push Services那条.
6.右键导出,存储为cert.p12,(输入密码P*d)。然后将该证书的折叠向下展开打开,导出“专用密钥”,存储为key.p12。
7.接下来打开终端执行下面的命令,生成的ck.pem就是我们在php脚本中要使用的证书。
#生成cert.pem
openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
#生成key.pem(先输出导出key.p12时设置的密码P*d, 然后设置一个新的密码,如pushpwd,这个密码后面php推送时要设置)
openssl pkcs12 -nocerts -out key.pem -in key.p12
#合并成ck.pem
cat cert.pem key.pem > ck.pem

voip证书制作

1、将之前生成的voip.cer SSL证书双击导入钥匙串
2、打开钥匙串访问,在证书中找到对应voip.cer生成的证书,右键导出并选择.p12格式,这里我们命名为voippush.p12,这里导出需要输入密码(随意输入,别忘记了)。
3、目前我们有两个文件,voip.cer SSL证书和voippush.p12私钥,新建文件夹命名为VoIP、并保存两个文件到VoIP文件夹。
4、把.cer的SSL证书转换为.pem文件,打开终端命令行cd到VoIP文件夹、执行以下命令
openssl x509 -in voip.cer  -inform der -out VoiPCert.pem
5、把.p12私钥转换成.pem文件,执行以下命令(这里需要输入之前导出设置的密码)
openssl pkcs12 -nocerts -out VoIPKey.pem -in voippush.p12
6、再把生成的两个.pem整合到一个.pem文件中
cat VoiPCert.pem VoIPKey.pem > ck.pem
最终生成的ck.pem文件一般就是服务器用来推送的。

PHP推送脚本:


<?php

// Put your device token here (without spaces):
//ios 14

$deviceToken = 'a2f1f16160d9ba6334b487728cd77cc98e461fc80b4d6a2e00804ffae1dad9d6';
//adhoc
$deviceToken = 'd2dc5ed03e7d5d900cafcfa7e47dafa0bbb809f8addb91de90257a518d67ea21';

//ios 11  
// $deviceToken = '108ce00ae4a02f8ce6204073b42a5b16c8c23b1e4eb5b3b127213fbd798c9c74';
//adhoc
$deviceToken = '478fe5d5fcd531434fe36baf4ebc34493786c114b2e979842a61a022838a1067';


$passphrase = '123456';
// $passphrase = '';


// Put your alert message here:
$message = 'MICHOI_M_CLOUDTALK_';

////////////////////////////////////////////////////////////////////////////////

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

// Open a connection to the APNS server
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
// $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;


$body['aps'] = array(
    'badge' => 1,
    'mutable-content'=>'1',
    'content-available' => '1',
    'apns-priority'=>'5',
    "alert"=>array(
        "title"=>"早游戏",
        "subtitle"=>"",
        "body"=>""
    ),
    'modify'=>'999',
    'sound'=>'default'

    );

// Encode the payload as JSON
$payload = json_encode($body);

// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));

if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);
    
?>

token参数是APP传给Apple的,拿来进行推送,在推送的时候最好自己搭个PHP服务,拿到token不然就无法实现一些其他测试了.
也附上代码:

<?php
/**
 * Created by VSCode.
 * User: mozi
 * Date: 2021/4/2
 * Time: 10:09
 */
 header("Content-Type:text/html;charset=utf-8");
    //1.接受数据
        $user=$_GET['user'];
        $token=$_GET['token'];
    //2.处理数据
        $str = '我的名字是'.$user.'我的token是'.$token;
    //3.返回结果
echo $str;
?>

注意:

关于token:重启是无法改变的.只有卸载才能重置.
关于证书:voip的证书deve和adhoc和App Store三种模式是同一个正式.
apns推送的证书要是dev模式和adhoc模式是不同的证书的.要制作不同的推送证书.
关于静默推送:静默推送在app处于后台未杀死的状态下是有意义的(只要推送里面的alert字段没有就行,远程推送是不能没有的不然Apple不会发送的).
关于voip:不好说,ios13以下还是好使的.



https://github.com/frankKiwi/FNKPushandVOIP.git

上一篇下一篇

猜你喜欢

热点阅读