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

发布于 2024-08-12 05:18:45 字数 1404 浏览 7 评论 0原文

我正在尝试使用 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 的数据包。 这是推送通知的二进制格式:

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

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

I'm trying to send a push notification to APNs using Erlang.
This is the code I came up with so far:

-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).

The code doesn't take advantage of Erlang's concurrency but is just a prototype. I only want to test if I can send the push in the most simple way.

I think the problem is in the packet being sent to the APNs.
This is the binary format of a push notification:

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

How should I create such a packet in Erlang?
Could someone please take a look at my code and tell me where the problem is?
Also I used Erlang's SSL application to create the connection and send the data and I don't know if this is the problem or the packet.
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

首先,不需要创建单个二进制文件的列表,然后对其调用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 指出了这个答案之前修订中的一些错误。

To start with, there is no need for creating a list of a single binary and then calling list_to_binary/1 on it. You can just send the binary itself.

Also, make sure the field lengths and values are appropriate according to the protocol:

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

Now that we have gotten this far, we will see that length(Token) is in fact 64, not 32:
You forgot to convert the hex string for Token to a binary, so you are sending a 64 byte hex character string instead of 32 binary bytes.

So... making Payload a binary from the start, and making Token a numeric constant, you can do something like the following:

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),

Thanks to Christian for pointing out a number of mistakes in the former revisions of this answer.

各空 2024-08-19 05:18:45

我看到两个错误:

  • 令牌应该以二进制形式传递,而不是以十六进制 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>>,

I see two mistakes:

  • Token should be passed in binary and not in hex ascii.
  • You can't use the binary syntax to turn lists into binaries.

For parsing hex to an integer and then down to binary use something like this:

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

Build the protocol packet with something like this:

TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,
浅唱々樱花落 2024-08-19 05:18:45

尝试使用一个简单的库 epns(Erlang 推送通知)

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

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

在 Erlang 20~21 上重新测试

Try use a simple library epns(Erlang Push Notifications)

This library can send push notification as APNS and FCM by Erlang side. How use epns(Erlang Push Notifications) library - you can read in README.md. This liblary can used as 3-rd party in project, or you can run it locally for see how this library works:

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

Retested on Erlang 20~21

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文