2009-11-18 41 views
20

Tôi đang cố gửi thông báo đẩy tới APN bằng Erlang. Đây là mã tôi đã đưa ra cho đến nay:Làm cách nào để gửi thông báo đẩy bằng Erlang?

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

Các mã không tận dụng đồng thời Erlang nhưng chỉ là một nguyên mẫu. Tôi chỉ muốn thử nghiệm nếu tôi có thể gửi push theo cách đơn giản nhất.

Tôi nghĩ rằng vấn đề nằm trong gói được gửi đến APN. Đây là định dạng nhị phân của một thông báo push:

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

Làm thế nào tôi nên tạo như một gói tin trong Erlang? Có thể ai đó vui lòng xem mã của tôi và cho tôi biết vấn đề ở đâu?
Ngoài ra tôi đã sử dụng ứng dụng SSL của Erlang để tạo kết nối và gửi dữ liệu và tôi không biết nếu đây là vấn đề hay gói.
Cảm ơn!

Trả lời

21

Để bắt đầu, không cần tạo danh sách nhị phân đơn và sau đó gọi list_to_binary/1 trên đó. Bạn chỉ có thể gửi bản thân nhị phân.

Ngoài ra, hãy chắc chắn rằng độ dài lĩnh vực và các giá trị phù hợp theo quy định của Nghị định thư:

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

Bây giờ chúng ta đã nhận này đến nay, chúng ta sẽ thấy rằng chiều dài (Token) là trong thực tế 64, chứ không phải 32 : Bạn quên chuyển đổi chuỗi hex cho Mã thông báo thành nhị phân, vì vậy bạn đang gửi chuỗi ký tự hex 64 byte thay vì 32 byte nhị phân.

... Vì vậy, làm Payload một nhị phân ngay từ đầu, và làm cho Mã một hằng số, bạn có thể làm một cái gì đó như sau:

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

Nhờ Christian để chỉ ra một số sai lầm trong các phiên bản cũ của câu trả lời này.

3

tôi thấy hai sai lầm:

  • Mã nên được thông qua ở dạng nhị phân và không có trong hex ascii.
  • Bạn không thể sử dụng cú pháp nhị phân để chuyển danh sách thành tệp nhị phân.

Đối với phân tích hex để một số nguyên và sau đó xuống một cái gì đó nhị phân sử dụng như thế này:

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

Xây dựng các gói dữ liệu giao thức với một cái gì đó như thế này:

TokenBin = ..., 
Payload = <<"Payload">>, 
PayloadSize = byte_size(Payload), 
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>, 
Các vấn đề liên quan