iOS推送通知(Push Notification)的Erlang实现

本文来自:瑞仙的Erlang开发博客

原文链接:http://blog.csdn.net/zhongruixian/article/details/39528765

一、前言

关于cer/pem证书转换,网上很多资料,我这就不说了,

网上有PHP实现的Push Notification,可以参考,

为了更好的做PUSH服务定制,我这里以Erlang(gen_server)实现iOS Push Notification

二、协议

1、协议分析

表1


名称


长度


描述


Command


1
字节


固定值:2


Frame length


4 字节


上图所有的Item总字节数(注意:不是Item个数)


Frame data


变长


详见表2

表2


名称


长度


描述


Item ID


1
字节


详见表3


Item data length


2
字节


Item data 字节数


Item data


变长


详见表3

表3


Item ID


名称


长度


Item data


1


Device token


32
字节


从客户端获取的device token(64字节的hex字符串)


2


消息(payload)


<= 256
字节


JSON格式,具体格式在这就不多说了,自己找吧


3


自定义的消息ID


4
字节


返回错误时,会把这个值透传回来


4


Expiration date


4
字节


UNIX时间戳


5


Priority


1
字节


传值10为立即发送

传值5为在Expiration date发送

2、协议数据打包实现

注意:网络字节序要有大端序

pack_frame(Cmd, Data) ->
    Len = byte_size(Data),
    <<Cmd:8, Len:16/big, Data/binary>>.

pack_frames(Frames) ->
    FramesBin = list_to_binary(Frames),
    FrameLen = byte_size(FramesBin),
    <<2:8/big, FrameLen:32/big, FramesBin/binary>>.

%% 16进制字符串转binary
hex_to_bin(Data) when is_binary(Data) ->
    hex_to_bin(binary_to_list(Data));
hex_to_bin(Data) ->
    hex_to_bin(Data, []).

hex_to_bin([H1, H2 | T], Rt) ->
    D1 = hex_to_oct(H1),
    D2 = hex_to_oct(H2),
    D = D1 bsl 4 + D2,
    hex_to_bin(T, [<<D:8>> | Rt]);
hex_to_bin([], Rt) ->
    list_to_binary(lists:reverse(Rt)).

hex_to_oct(N) when N >= 48, N =< 58 ->
	N - 48;
hex_to_oct(N) when N >= 65, N =< 70 ->
	N - 55;
hex_to_oct(N) when N >= 97, N =< 102 ->
	N - 87.

三、PUSH实现过程

1、SSL启动

ssl:start()

2、SSL连接(gen_server代码片段)

-record(state, { ssl_socket }).

start_link() ->
    gen_server:start_link({local, push}, ?MODULE, [], []).

init([]) ->
    {ok, #state{}}.

handle_info(connect, State) ->
    try
        TcpOptions = [binary, {packet, 0}, {nodelay, true}, {delay_send, true}, {exit_on_close, false}],
        SslOptions = [ {password, "1234"} ,{keyfile, "./dev_msttd_aps.pem"} ,{certfile, "./dev_msttd_aps.pem"},

        Options = TcpOptions ++ SslOptions,
        case ssl:connect("gateway.sandbox.push.apple.com", 2195, Options, 30000) of
            {ok, Socket} ->
                ?INFO("~npush connect OK:~n~w", [Socket]),
                {noreply, State#state{ssl_socket = Socket}};
            {error, Error} ->
                ?INFO("~w", [Error]),
                {noreply, State}
        end;
        catch T : X ->
            ?INFO("~p:~p~n~p", [T, X, erlang:get_stacktrace()]),
            {noreply, State}
    end;

3、向一个设备PUSH消息(gen_server代码片段)

handle_info({send, DeviceToken1}, State) ->
    try
        Time = util:unixtime(),
        DeviceToken = hex_to_bin(DeviceToken1),
        Payload = <<"{\"aps\":{\"alert\":\"《萌獸堂》萌獸等你來戰!\",\"sound\":\"default\"}}">>,
        PayloadLen = byte_size(Payload),
        Frame1 = pack_frame(1, DeviceToken),
        Frame2 = pack_frame(2, Payload),
        Frame3 = pack_frame(3, <<Time:32/big>>),
        Frame4 = pack_frame(4, <<Time:32/big>>),
        Frame5 = pack_frame(5, <<10:8/big>>),
        Data = pack_frames([Frame1, Frame2, Frame3, Frame4, Frame5]),
        case ssl:send(State#state.ssl_socket, Data) of
            ok -> ?INFO("send ok (~s)", [DeviceToken1]);
            Error -> ?INFO("send error:~p", [Error])
        end
        catch T : X ->
            ?INFO("~p:~p~n~p", [T, X, erlang:get_stacktrace()])
    end,
    {noreply, State};

4、错误处理(gen_server代码片段)

handle_info({ssl, _,<<8:8, StateCode:8, Id:32/big>>}, State) ->
    %% TODO: 出错啦,根据StateCode来具体处理吧
    ?INFO("Error: ~w - ~w", [StateCode, Id]),
    {noreply, State};

四、使用实例

push ! connect.

push ! {send, "8333801EBED044241D35C182F9F5CED47231D56A398AA1991060E3086699FE9F"}.

时间: 2024-08-06 07:54:59

iOS推送通知(Push Notification)的Erlang实现的相关文章

iOS 推送通知流程

别的不说,现在AppDelegate.m中添加以下代码块 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     // 将这行代码插入     [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationT

Clojure:两步发送iOS推送通知(apns)

首先在project.clj中,添加对notnoop 类库的引用:[com.notnoop.apns/apns "0.2.3"] 然后使用如下方法就可以发送推送消息了: 1 (ns demo.apns 2 (:import (com.notnoop.apns APNS))) 3 4 (defn send-push-notification 5 [device-tokens message] 6 (loop [rest-device-tokens device-tokens 7 sent

IOS推送通知测试工具PushMeBaby

下载了PushMeBaby在xcode5里中不能使用,类库变了.需要添加Carbon.framework库,在引用的地方改成: #include <Carbon/Carbon.h>,程序就可以 运行了.测试时要变成自己的证书. 下载地址:点击打开链接 IOS推送通知测试工具PushMeBaby,码迷,mamicode.com

IOS推送功能push

笔记:ios推送功能 推送可实时提醒用户你想要让客户端用户知道的信息,那怕用户并没有开启这个应用.应用场景很广泛,如淘宝应用:在你使用淘宝客户端的时候,假如你拍的东西发货了,如果没有推送功能,你不会及时知道你拍下的东西已经发货.但使用了推送后,淘宝就会发送一条推送通知,告知使用客户端App的你,你拍下的东西已经发货.使用推送的场景很多,在用户的体验度上更人性. 苹果的推送机制(APNS)咯(ps:其实每一篇教程都有),先来看一张苹果官方对其推送做出解释的概要图. Provider是给你手机应用发

【PHP】iOS推送通知以及反馈服务

近来项目是完成一个PHP的推送服务器,无论是PHP,APNs还是GCM基本上都是从零开始. 写下一点见解,方便以后继续做代码的搬运工. 因为对PHP跟iOS都不熟悉,可能有错漏...穷孩子没有用过iOS的东西... 设备如果希望能够及时收到服务器的消息,大概有三种方式: 1)轮询(Pull)方式:客户端与服务器主动连接查询.因为及时性以及耗电量等要求不可得兼,一般不考虑. 2)SMS(Push)方式:在Android平台,可以通过拦截SMS消息并且解析消息内容来了解服务器的意图,并获取其显示内容

ios推送通知之ios推送证书的申请和使用配置

很多人初次接触推送通知,不知道怎么去申请ios推送证书和配置推送. 很多人犯的错误就是用推送证书p12去打包ipa,推送不是用来打包的,下面详细介绍ios推证书的申请和配置使用. ios推送证书分为测试调试用的iOS推送证书(开发环境)和上架到App Store的ios 推送证书!(生产环境) APP要推送通知首先要在创建APPID时勾选推送服务. 推送证书是配置上传到推送平台的,如极光推送.个推.小米推送等,不是用来打包ipa的,下面会有介绍. 一.创建唯一标示符App IDs 首先打开开发者

APNS 远程推送通知 PUSH deviceToken

服务器向客户端推送消息: 当应用程序推到后台,或者根本就没有运行(我们的代码无能为力)      如果这种情况之下,应用程序想和用户交互(传统的做法 不可能) 推送 APNS:Apple Push Notification Service deviceToken:标示某一台iPhone上的某一个应用程序 1.(用户必须确认需要收到推送消息)注册远程通知中心向APNS获取64位的字符串deviceToken 注册远程通知中心 [[UIApplication sharedApplication] r

iOS推送通知

一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图1-1: 1.Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]): 2.APNS:Apple Push Notification Service[苹果消息推送服务器]: 3.iPhone:用来接收APNS下发下来的消息: 4.Client App:IOS设备上的应用程序,用来接收iphone传递APNS下发的消息到制

iOS 推送通知中那些让你故意犯的错误~

最近两天的工作中被推送这个玩意儿折磨了好一会,还好经过"不懈地"努力,弄明白了其中的原理.目前大部分app中使用的推送基本上都是第三方集成好的,都有官方的代码,所以写起来还是非常简单的.这里记录的是其中不可避免的,而官方文档中又可能没有提到的一些问题的解决方法. 首大家要搞清楚2个证书的使用位置,一个是开放证书,另一个是生产证书.一般在使用第三方集成的推送库中,都会要求上传这2个已经转化为.pem格式的证书.前者是在测试阶段时使用的,在真机上测试推送时,记得要选择开发模式,而且要记得把