我们的IOS移动应用要实现消息推送,告诉用户有多少条消息未读,类似下图的效果(笑果),特把APNS和Erlang相关解决方案笔记于此备忘.
 
   
   上面图片中是Apple Notification在UI展现的形式之一,Notification共有三种形式:图标显示更新数字(badge),提示信息(alert),提示音(sound);
 
   iOS Apple Push Notification Services (APNs)官方的开发文档位置在:[Apple Push Notification Services],iOS团队的Matthijs Hollemans写的入门文档:Apple Push Notification Services in iOS 6 Tutorial 从这两份文档中,可以了解APNs的设计和开发的各种细节.首先是APNS的设计初衷:当用户没有启动应用,或者没有开机那么应用Server想要推送的消息就无法到达,需要其他的机制来完成消息的投递.
 
  Apple Push Notification service (APNs)把消息推送到设备上,设备上有应用已经注册过要接受此类消息.这里会有三种角色:Provider, APNs,Device . 见下图:
 
   
  
 
     上图说明:消息提供者(Provider),Provider接入到APNs,把最新的消息推送到 APNs,然后由APNs推送到目标设备(Device)的指定应用(Client APP).
 
      从上面的图,可以提出很多问题,特别是考虑到一些极端情况的时候,很有意思,可以通过这些问题驱动阅读Apple开发文档:
  1. Provider,APNs,Device 这三者之间的信任关系是怎么建立?
  2. 如何标识消息是给哪台机器的哪个应用的?消息传递的协议是怎么设计的(如何承载要发送的消息)?
  3. 在Device离线的情况下,Provider提交N条要发送给该Device的消息到APNs,APNs如何处理?
  4. 对于一些极端情况:比如Device做了系统恢复,应用卸载,Device硬件损坏,APNs有哪些应对机制?
  
    首先解决三者的信任关系,Provider(APP Server)的开发方要从Apple Dev Center获得SSL证书, 每个证书一个应用,甚至开发和生产环境的证书都要分别申请. Provider要在APNs中进行认证注册,目前注册使用的是应用程序的唯一标识(bundle identifier).Provider Connection的是对应到指定应用的,certificate中包含了应用程序的标识信息(bundle ID),APNs维护了一个废弃列表,如果一个Provider上了名单,APNs就会移除对该应用的信任. Provider和APNs通信协议是二进制协议,使用TCP流协议建立SSL(TLS)安全连接,官方文档称这种信任为Connection Trust. 
 
    对于用户设备APNs使用的是Token Trust.用户安装一个APP的时候,如果APP需要消息推送功能通常在安装成功之后会经由用户设备发起注册请求,用户设备将此请求转发到APNs, APNs生成唯一的device certificate,其中包含了device token.Device Token 中包含了设备的唯一标识,使用Token key加密Device Token返回到Device.用户设备把device token返回给发起注册请求的应用程序,应用程序把Device Token的信息传递给Provider.用户设备上安装的APP从APNs 获得device token之后每一次连接到ANPs都要提供这个token. APNs解密device token并验证这个token是从连接过来的设备生成的:APNs保证实际连接过来的设备标识和certificate文件中里面包含的标识一致.
 
   Provider提交到APNS的notification两个必要的信息:把什么消息投递给谁,即包含设备标识(Device Token)和实际消息体(Payload).APNS使用token Key解密token,从中提取设备ID来决定最终消息投递到哪个设备.Device Token有一个非常贴切的类比:手机号,它包含的信息可以让APNs来定位安装了指定应用的设备.APNs还使用Device Token来路由消息,Payload的消息组织形式是类JSON的,它包含的信息包括推送给设备什么内容以及如何提示;Payload内容大小限制是 256 bytes.
  注意:Device Token和设备的UDID不是一回事,用户恢复系统,重装都会导致device token变化.
 
    APNs有一个 Feedback Service的设计,它维护应用消息推送失败的设备列表,如果应用已经卸载了就无法投递成功,这样Feedback Service里面就会有记录.Provider的开发方应定期从该服务拉取这个失败列表来调整自己的发送行为:不要再给一个总是失败的设备推送消息了.如果设备离线,notification会在APNs上保存有限的一段时间,设备上线之后完成推送.如果设备离线期间同一个应用推送了多条notification,那么只会保存最新的notification,如果设备长期离线,任何离线消息都会被抛弃掉.这样如果iPhone掉海里面,需要推送给它的消息在过期之后就会被清理掉,不会长久占用APNs的资源.
 
 
  
 
经过上面的分析基本可以列出Erlang实现消息推送的技术要点了:
[1] JSON数据解析构造 mochijson mochijson2之类的模块就可以搞定  mochijson:encode --> list_to_binary
[3] 二进制协议实现 (Apple Binary Iterface)
Packet = [<<1:8, MsgId/binary, Expiry:4/big-unsigned-integer-unit:8,
                32:16/big,
                BinToken/binary,
                PayloadLength:16/big,
                BinPayload/binary>>]
 
[4] deviceToken -> binary 需要hexstr_to_bin的方法,这个代码片段之前说过多次了
bin_to_hexstr(Bin) ->
lists:flatten([io_lib:format("~2.16.0B", [X]) ||
X <- binary_to_list(Bin)]). hexstr_to_bin(S) ->
hexstr_to_bin(S, []).
hexstr_to_bin([], Acc) ->
list_to_binary(lists:reverse(Acc));
hexstr_to_bin([X,Y|T], Acc) ->
{ok, [V], []} = io_lib:fread("~16u", [X,Y]),
hexstr_to_bin(T, [V | Acc]).
[5] 维护TCP连接,重连机制
 
按照上面的要点完成了基本的验证之后,在Github上找到了开源项目apns4erl (地址:https://github.com/inaka/apns4erl),这个项目对APNS服务做了良好的实现和封装.下面介绍下apns4erl的使用:
 
 

开源项目APNS4erl

 
证书制作:
  APP Server和Apple Server中间建立信任关系需要通过各种证书,apns4erl作者在项目中提供了生成证书的脚本,不过在项目首页提到.cer和.p12文件生成pem证书的脚本地址是错的,实际位置是:
 
执行下面的脚本就一步一步即可:

#!/bin/sh

# Usage:
# test_certs {cert_file} {private_key_file}
# Example:
# test_certs aps_developer_indetity.cer aps_developer_identity.p12 mkdir -p priv/temp
openssl pkcs12 -in "$2" -out priv/temp/key-enc.pem
openssl rsa -in priv/temp/key-enc.pem -out priv/temp/key.pem
openssl x509 -inform der -in "$1" -out priv/temp/cert.pem
cat priv/temp/cert.pem priv/temp/key.pem > priv/cert.pem
rm -rf priv/temp
make test
下面是测试代码,注意send_badge/1方法就是我们需要的效果:
-module(t).
-compile(export_all).
-define(APNS_NAME,app_apns). -include("apns.hrl").
-include("localized.hrl"). conn_apns() ->
ssl:start(),
apns:start(),
apns:connect(
?APNS_NAME,
fun handle_apns_error/,
fun handle_apns_delete_subscription/
). send_message()->
apns:send_message(?APNS_NAME, "devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff", "hello,这是一号话务员"). send_message(Msg) ->
apns:send_message(my_connection_name, #apns_msg{
alert = Msg ,
badge = ,
sound = "beep.wav" ,
expiry = ,
device_token = "devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff"
}). send_badge(Number)->
apns:send_badge(qiaoqiao_apns,"devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff", Number). handle_apns_error(MsgId, Status) ->
error_logger:error_msg("error: ~p - ~p~n", [MsgId, Status]). handle_apns_delete_subscription(Data) ->
error_logger:info_msg("delete subscription: ~p~n", [Data]).
APNS相关资料:
 
 
[0] iOSDeveloper Library: Apple Push Notification Service (APNS)
 
[1] Apple Push Notification Services in iOS 6 Tutorial
 
[2]  Apple Push Notification Services in iOS 6 Tutorial 中文
 http://www.raywenderlich.com/zh-hans/24732
 
[3] iOS 和 Android 的后台推送原理各是什么?有什么区别?
 
[4] 苹果产品是如何实现推送功能的呢?
 
[5] 为什么 Android 的后台推送不如 iOS 的推送使用广泛?
 
[6]  Is the device token as unique as the device ID?
 
[7]  If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes. https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
 
[8] Apple Push Notifications with Erlang
 
[9] Sending Apple Push Notifications with Erlang
 
最后小图一张:
 

[Erlang 0106] Erlang实现Apple Push Notifications消息推送的更多相关文章

  1. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)

    什么是GCM? Google Cloud  Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...

  2. (转)在SAE使用Apple Push Notification Service服务开发iOS应用, 实现消息推送

    在SAE使用Apple Push Notification Service服务开发iOS应用, 实现消息推送 From: http://saeapns.sinaapp.com/doc.html 1,在 ...

  3. Push:iOS基于APNS的消息推送

    1. Push的三个步骤,如下图所示: (1)Push服务应用程序把要发送的消息.目的iPhone的标识打包,发给APNS: (2)APNS在自身的已注册Push服务的iPhone列表中,查找有相应标 ...

  4. [置顶] 手把手教你iOS消息推送证书生成以及Push消息

    iOS推送消息是许多iOS应用都具备的功能,今天在给应用加推送功能,在生成证书的过程中,发生了各种令人蛋痛的事.下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provi ...

  5. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  6. 为友盟消息推送开发的PHP SDK(composer版):可以按省发Android push

    一直以来APP希望按省市县推送Android push,只能自己分析用户经纬度,打tag发送. 现在终于有服务商提供了. 友盟消息推送 可以“按省推送”,很方便. 我为友盟做了PHP SDK(comp ...

  7. 带你了解什么是Push消息推送

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 如果有看我最近文章的同学可能就知道我在公司负责的是一 ...

  8. APP消息推送机制的实现(PUSH)

    出于好奇,想了解一下消息推送机制,在网上搜索到了几篇文章,感觉还不错,粘贴下来,等真正用到的时候再仔细研究 以下两篇是关于ios的 1.http://blog.csdn.net/xyxjn/artic ...

  9. 采用MQTT协议实现android消息推送(2)MQTT服务端与客户端软件对比、android客户端示列表

    1.服务端软件对比 https://github.com/mqtt/mqtt.github.io/wiki/servers 名称(点名进官网) 特性 简介 收费 支持的客户端语言 IBM MQ 完整的 ...

随机推荐

  1. java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。

    转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...

  2. 1Z0-053 争议题目解析501

    1Z0-053 争议题目解析501 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 501.Note the output of the following query; SQL&g ...

  3. iOS_MJRefrash的详解以及使用

    MJRefresh Github 效果动态图来这里看吧 该博客Demo下载地址 一. MJRefresh的类解释. 1.MJRefreshComponent              所有刷新控件的基 ...

  4. WebSocket 介绍(一)

    WebSocket 发起单个请求,服务端不需要等待客服端,客户端在任何时候也能发消息到服务端,减少了轮询时候的延迟.经历一次连接后,服务器能给客户端发多次.下图是轮询与WebSocket的区别. 基于 ...

  5. ASP.NET Core 开发-中间件(Middleware)

    ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...

  6. 安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2出现0x80072f8a未指定的错误

    本文转载自: http://www.cnblogs.com/JiaoWoWeiZai/p/5892255.html 最近DotNetCore更新到了1.0.1,Azure tools也更新到了2.9. ...

  7. C#+ArcEngine10.0+SP5实现鼠标移动动态显示要素属性信息

    为了解决鼠标移过动态显示要素属性的问题,我在网上先是查到的只能显示单个要素的属性,就是直接在arcmap中设置好的那个tips就可以显示,但是这种显示效果只是简单的实现了显示要素的属性值,可是没有对该 ...

  8. Oracle学习总结_day03_day04_条件查询_排序_函数_子查询

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day03_条件查询_排序_函数 清空回收站: PUR ...

  9. JAVA 异常处理机制

    主要讲述几点: 一.异常的简介 二.异常处理流程 三.运行时异常和非运行时异常 四.throws和throw关键字 一.异常简介 异常处理是在程序运行之中出现的情况,例如除数为零.异常类(Except ...

  10. PostgreSQL保存文件到数据库

    1.CREATE TABLE public.t_file ( id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('t_file_id_seq'::regc ...