首页 > 代码库 > iOS推送通知(Push Notification)的Erlang实现
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 = http://www.mamicode.com/pack_frames([Frame1, Frame2, Frame3, Frame4, Frame5]),>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"}.iOS推送通知(Push Notification)的Erlang实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。