标签:erlang ios push 推送 notification
本文来自:瑞仙的Erlang开发博客
原文链接:http://blog.csdn.net/zhongruixian/article/details/39528765
关于cer/pem证书转换,网上很多资料,我这就不说了,
网上有PHP实现的Push Notification,可以参考,
为了更好的做PUSH服务定制,我这里以Erlang(gen_server)实现iOS Push Notification
|
名称 |
长度 |
描述 |
|---|---|---|
|
Command |
1 字节 |
固定值:2 |
|
Frame length |
4 字节 |
上图所有的Item总字节数(注意:不是Item个数) |
|
Frame data |
变长 |
详见表2 |
|
名称 |
长度 |
描述 |
|---|---|---|
|
Item ID |
1 字节 |
详见表3 |
|
Item data length |
2 字节 |
Item data 字节数 |
|
Item data |
变长 |
详见表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发送 |
注意:网络字节序要有大端序
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.
-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;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};handle_info({ssl, _,<<8:8, StateCode:8, Id:32/big>>}, State) ->
%% TODO: 出错啦,根据StateCode来具体处理吧
?INFO("Error: ~w - ~w", [StateCode, Id]),
{noreply, State};iOS推送通知(Push Notification)的Erlang实现
标签:erlang ios push 推送 notification
原文地址:http://blog.csdn.net/zhongruixian/article/details/39528765