22

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

-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 的数据包中。这是推送通知的二进制格式:

替代文字 http://developer.apple.com/IPhone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_provider_binary.jpg

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

4

3 回答 3

23

首先,不需要创建单个二进制文件的列表然后调用list_to_binary/1它。您可以只发送二进制文件本身。

此外,请确保字段长度和值根据协议是适当的:

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

现在我们已经到了这一步,我们将看到 length(Token) 实际上是 64,而不是 32:您忘记将 Token 的十六进制字符串转换为二进制,所以您发送的是 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在此答案的先前修订版中指出了许多错误。

于 2009-11-18T16:34:37.977 回答
4

我看到两个错误:

  • 令牌应该以二进制而不是十六进制 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>>,
于 2009-11-18T17:41:44.027 回答
1

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

该库可以通过 Erlang 端将推送通知作为 APNS 和 FCM 发送。如何使用epns(Erlang 推送通知)库 - 您可以在README.md中阅读。该库可以用作项目中的 3-rd 方,或者您可以在本地运行它以查看该库的工作原理:

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

在 Erlang 20~21 上重新测试

于 2019-08-01T09:07:21.753 回答