如何使用Erlang发送推送通知?

时间:2009-11-18 16:17:12

标签: erlang binary push apple-push-notifications

我正在尝试使用Erlang向APN发送推送通知。 这是我到目前为止提出的代码:

-module(apnstest2).
-export([connect/0]).

connect() ->
    application:start(ssl),
    ssl:seed("someseedstring"),
    Address = "gateway.sandbox.push.apple.com",
    Port = 2195,
    Cert = "/path/to/Certificate.pem",
    Key = "/path/to/Key.unenc.pem",
    Options = [{certfile, Cert}, {keyfile, Key}, {mode, binary}],
    Timeout = 1000,
    {ok, Socket} = ssl:connect(Address, Port, Options, Timeout),

    Token = "195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03",
    Payload = "{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}",
    TokenLength = length(Token),
    PayloadLength = length(Payload),

    Packet = [<<0:8, TokenLength, Token, PayloadLength, Payload>>],

    ssl:send(Socket, list_to_binary(Packet)),
    ssl:close(Socket).

代码没有利用Erlang的并发性,但只是一个原型。我只想测试是否可以用最简单的方式发送推送。

我认为问题在于发送到APN的数据包。 这是推送通知的二进制格式:

alt text http://developer.apple.com/IPhone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_provider_binary.jpg

我应该如何在Erlang中创建这样的数据包? 有人可以看看我的代码并告诉我问题在哪里吗? 我还使用Erlang的SSL应用程序创建连接并发送数据,我不知道这是问题还是数据包。
谢谢!

3 个答案:

答案 0 :(得分:21)

首先,不需要创建单个二进制文件的列表,然后在其上调用list_to_binary/1。你可以直接发送二进制文件。

另外,请确保字段长度和值适合根据协议:

TokenLength = 32 = length(Token),
Packet = <<0:8, TokenLength:16/big, Token, PayloadLength:16/big, Payload>>,
ssl:send(Socket, Packet),

既然我们已经走到这一步,我们将看到长度(令牌)实际上是64,而不是32: 您忘记将令牌的十六进制字符串转换为二进制,因此您发送的是64字节十六进制字符串而不是32字节字节。

所以......从一开始就使Payload成为二进制文件,并使Token成为一个数字常量,你可以做类似以下的事情:

Payload = <<"{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}">>,
PayloadLength = size(Payload),
Packet = <<0:8, 32:16/big,
          16#195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03:256/big,
          PayloadLength:16/big, Payload/binary>>,
ssl:send(Socket, Packet),

感谢Christian指出了此答案的前修订中的一些错误。

答案 1 :(得分:3)

我看到两个错误:

  • 令牌应该以二进制形式传递,而不是以十六进制传递ascii。
  • 您无法使用二进制语法将列表转换为二进制文件。

要将十六进制解析为整数然后再解析为二进制,请使用以下内容:

Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,

使用以下内容构建协议包:

TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,

答案 2 :(得分:0)

尝试使用简单的库epns(Erlang Push Notifications)

该库可以通过Erlang端以APNS和FCM的形式发送推送通知。 epns (Erlang推送通知)库的使用方法-您可以在 README.md 中阅读。该库可以在项目中用作第三方,也可以在本地运行该库以查看该库的工作方式:

$ git clone https://github.com/vkatsuba/epns.git
$ cd epns
$ make

在Erlang 20〜21上重新测试