苹果推送APNS的一个容易错误的地方

   在网上看了很多的apns的介绍,我看了大多都是PHP的讲解如何服务器对接苹果服务器以及发送推送,我这边就不介绍苹果APNS的原理了,不过其中有几个需要介绍的地方。需要注意

一、苹果服务器有两种连接方式

1,HTTP/2,这是苹果APNS在2015年12月份弄出来的,这个新版本的协议基于HTTP/2和JSON。有一篇文章总结的很好,我就直接复制过来,方便点。

原文地址:http://www.oschina.net/translate/http2-protocol-for-apns?cmp

新的APNS协议基于HTTP/2:

苹果推送APNS的一个容易错误的地方_第1张图片

新的特性和功能:

  • 基于JSON的请求和响应

  • 对于每个通知,如果成功响应,将会返回200标识 - 不用再去猜测通知是否被接收到

  • 响应错误将会以JSON字符的形式返回

  • 消息的长度从2048个字节增加到4096个字节

  • 连接状态可以通过HTTP/2的ping框架来进行检查

  • 支持主题

  • 通用的推送证书 - 开发和生产使用同一个证书即可

需要连接的端口是

  • Development server: api.development.push.apple.com:443

  • Production server: api.push.apple.com:443


今天讲解的重点不在这里,原因是笔者我在重构公司的推送服务器的时候用的C开发,而当时使用的CURL版本太低了,而且CURL在7.47.0才开始支持HTTP2,并且需要nghttp(至少1.0.0)的支持,而本身部署服务器的环境不太好改动,因此就作罢,苹果本身是很支持使用HTTP2,我以后会想办法用python来处理的。

CURL处理HTTP2的说明:点击这里

基于HTTP2的官网文档:点击这里

2,第二种连接方式叫做 binary interface,今天的重点也是这个

旧的APNS二进制协议

苹果推送APNS的一个容易错误的地方_第2张图片

旧的二进制APNS协议有点奇特,一般来说,推送分发的服务器要打开一个同APNS网关服务器的socket连接,并保持这个连接。在旧的协议下,如果服务器响应成功的话,你将不会收到任何回应,但是如果服务器响应失败(例如,使用了一个非法的Push token),服务器将返回了一个错误编码,并关闭这个socket。最重要的是,你必须重新发送使用这个无效token以后发送的所有通知。因此,你可能一直不能确定你的推送是否成功的被服务器接收。许多系统使用这个漏洞,故意发送一个错误的token,这些黑客行为将导致系统性能低下。苹果有一个名为"feedback"的服务,我们可以定时调用这个服务来获取invalid tokens的列表。这个服务你只要调用一次就可以获得所有的invalid tokens 列表。所以,如果一个应用有许多推送通知提供商,他们将会争夺资源去轮询查找invalid tokens列表。invalid token越多,你系统性能将越低,所以APNS只要一发生错误就关闭这个连接。


连接Binary Interface的接口:

production environment :    gateway.push.apple.com, port 2195

development environment:  gateway.sandbox.push.apple.com, port 2195


Binary Interface的官网文档: 点击这里


Binary Interface 有三种推送的格式,可以简单称为V1,V2,V3(个人称呼)


V1是最简单的,格式如下:

Legacy Notification Format

苹果推送APNS的一个容易错误的地方_第3张图片


APNS是根据Command来区分不同的推送格式的,其中V1的格式Command固定为0.

后面跟着token的大小以及二进制的token,

token之后跟着json的大小以及json内容,看图上说的是限制为大小为34,具体没有测试过,我记得应该是整个报文大小限制为256,这个不用考究。因为这是最差的格式了。

该格式的有很多弊端,比如

1,发送成功后,不知道apns是否处理。

2,如果出错,也只是apns也只会关闭掉socket对端,而没有反馈信息。

因此这也不是现在所需要采纳的。

V2格式是因为苹果被不停地反馈而推出的格式。该格式如下;

Enhanced Notification Format

https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_binary_provider_2_2x.png

该格式有如下优点:

1,增加了identifier字段,这个是由我们这边的server定义的,官网文档说的是如果发生了错误,则会返回最后成功的那次的identifier(其实是错误的那个),因此我们可以根据这个字段来判断在什么时间出错,那么后面发送的推送就都不可靠,因此需要重新发送一次,因为apns有一个很坑爹的地方就是如果你发送了100个推送,其中第50个错误了,当他通知你第50个错误的时候,有可能后面的50个推送是没办法成功的(有些推送会有很低的概率成功,很少见),因此需要重新发送后面这50个推送。

2,增加了Expiry字段,这个字段由我们Server自己定义,及这个推送的超时时间,如果超过了这个时间,就自动不推送了。

但是依然不算最好的格式,如果你发送的报文比较小还好,如果大了,依然有限制要求。


重点讲述的是V3格式,该格式如下:

官网文档:点击这里

The Binary Interface and Notification Format

https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_binary_provider_3_2x.png


Note: All data is specified in network order, that is big endian.


The top level of the notification format is made up of the following, in order:

Field name

Length

Discussion

Command

1 byte

Populate with the number 2.

Frame length

4 bytes

The size of the frame data.

Frame data

variable length

The frame contains the body, structured as a series of items.

The frame data is made up of a series of items. Each item is made up of the following, in order:

Field name

Length

Discussion

Item ID

1 byte

The item identifier. For example, the item number of the payload is 2.

Item data length

2 bytes

The size of the item data.

Item data

variable length

The value for the item.

The items and their identifiers are as follows:

Item ID

Item Name

Length

Data

1

Device token

32 bytes

The device token in binary form, as was registered by the device.

2

Payload

variable length, less than or equal to 2 kilobytes

The JSON-formatted payload.

The payload must not be null-terminated.

3

Notification identifier

4 bytes

An arbitrary, opaque value that identifies this notification. This identifier is used for reporting errors to your server.

4

Expiration date

4 bytes

A UNIX epoch date expressed in seconds (UTC) that identifies when the notification is no longer valid and can be discarded.

If this value is non-zero, APNs stores the notification tries to deliver the notification at least once. Specify zero to indicate that the notification expires immediately and that APNs should not store the notification at all.

5

Priority

1 byte

The notification’s priority. Provide one of the following values:

  • 10 The push message is sent immediately.

    The remote notification must trigger an alert, sound, or badge on the device. It is an error to use this priority for a push that contains only thecontent-available key.

  • 5 The push message is sent at a time that conserves power on the device receiving it.

    Notifications with this priority might be grouped and delivered in bursts. They are throttled, and in some cases are not delivered.

这里我是直接粘贴过来的, 其实我讲述这边文章也是为了提醒我自己和广大朋友一个比较坑爹的事情,当然也是自己不小心才会这样的,

只是看官网的文档,感觉是一个frame data里面有很多的item,每个item都是一个推送,感觉是可以批量推送的。

每个item里面包含item_id和item_length以及item_data, 而item_data又由Device token和Payload等组成。

然而这是错误的

其实是这个图片误导了我们,我当时看了很多的英文文档,以及很多提问的,包括很多老外都以为是这样,结果在发送报文的时候,老是得到错误的应答,搞得都很无语了,最后我才发现:

V3其实描述的还是一个推送,而一个item是一个tlv的格式,item_id 1,2,3对应上表的token、payload等,真是心痛。,

按照tlv的结构发送报文就可以了。

写这篇文章,警示自己。



你可能感兴趣的:(C语言,C++)