GCM架构概览

(新手翻译,请批评指正)译文链接:GCM Architectural Overview

GCM架构概览

Android的谷歌云消息服务(Google Cloud Messaging,简称GCM)是一个免费的服务,主要用来帮助开发者从自己的服务器发送消息到安装他们程序的Android设备,并且获取从用户的设备返回到云端的消息。发送的消息一般都是轻量的,用来告诉Android程序有新的数据需要从服务器拉取(例如,朋友上传的一个电影),或者是一个包含4kb及以下的有效载荷数据(所以应用程序如即时消息就可以直接处理掉这个数据)。GCM服务处理各种各样的消息队列,发送给给运行在目标设备上的目标程序。

GCM介绍了谷歌云服务连接服务器(Cloud Connection Server,简称CCS),你可以使用它来配合GCMHTTP服务/端点/APIS。CCS使用XMPP协议(Extensible Messaging and PresenceProtocol, 可扩展消息与存在协议),它提供异步的、双向的消息。更多的内容,见GCM Cloud Connection Server.

想直接使用GCM来处理你的Android程序,见Getting Started的指导。

快速一览

  • 获得对关键字GCM的术语和概念的介绍。
  • 学习一个GCM程序最基本的特性。
  • 明白第三方程序服务器的角色和如何发送消息和处理结果。

简介

这里是GCM的最基本的特性:

  • 允许第三方程序服务器发送消息给他们的Android程序。
  • 使用GCM 的CCS服务器,你能够获得从手机设备传回的消息。
  • 一个Android设备上的程序不需要运行来接受消息。当消息到来的时候,只要程序设置了合适的广播接收器和权限,系统会通过广播唤醒该程序。
  • GCM不提供任何嵌入的用户接口或者其他处理消息数据的方法。GCM只是简单直接的传递收到的未加工的消息数据到Android程序,这个程序有处理数据的全部控制权限。例如,程序可能发送了一个通知,显示一个用户界面,或者默默的同步数据。
  • 需要Android2.2或以上版本的设备,还必须要安装Google Play Store,或者Android2.2以上程序版本带有Google APIS的虚拟机。然后,你并没有受到必须通过Google Play Store配置你的程序的限制。
  • GCM使用谷歌服务的一个已经存在的连接。对于3.0之前的设备,或者可能需要用户设置谷歌账户。对于Android4.0.4或以上的版本,谷歌账户并不是必须的。

架构概览

这节展示GCM工作的概览。

下表总结了GCM中关键的术语和概念。划分为以下几类。

  • 组件 — 在GCM中的物理实体。
  • 凭证 — GCM不同层次的ID和符号,保证所有的部分都是认证的,消息能够到达正确的地方。

组件

手机设备

这是一个运行使用GCM的Android程序的设备。必须是Android2.2以上的的安装Google Play Store的设备,如果低于Android4.0.4版本的设备还必须有至少一个登录的谷歌账户。还可以选择另一种方式用来测试,使用运行在Android2.2以上带有Google APIs的虚拟机。

第三方程序服务器

一个程序服务器,开发者在他们程序中实现GCM的一个部分。第三方程序服务器通过GCM服务器发送数据到设备的Android程序。

GCM服务器

从第三方程序服务器获得消息并发送给设备的谷歌服务。

 

凭证

发送者ID

(Sender ID)

开始章节所说的你从API控制台获得的项目编号。发送者ID在注册过程的时候用来认证一个Android的程序是否被允许发送消息给设备。

程序ID

(Application ID)

注册接受消息的Android程序。Android程序能够根据manifest中的包名加以区分。这保证了消息对应了正确的Android程序。

注册ID

(Registration ID)

由GCM服务器发行的允许Android程序接收消息的ID。一旦Android程序有了注册ID,它就发送给第三方程序服务器,第三方服务器用来区已经注册了指定接受消息的Android程序。换句话说,一个注册ID已经和一个运行在独一无二的设备上的独一无二的程序绑定了。
注意:如果你是用了备份和回复,你应该明确的拒绝备份注册ID。当你备份一个设备的时候,程序不加选择的备份了shared prefs。如果你不明确的把GCM注册ID排除在外,就不能被在一个新的设备上重新弄使用,这可能会导致传递错误。

谷歌用户账户

(Google User Account)

如果设备运行在低于Android4.0.4版本的系统,为了让GCM工作,设备必须包含至少一个谷歌账户。

发送者认证令牌

(Sender Auth Token)

第三方程序服务器保存了一个API key用来赋予程序服务器接入谷歌服务的权利。这个API key在发送消息的时候被包含在POST请求的头部。

通知键

(Notification Key)

部分用户通知的特性,提供了一个在用户和和运行在他的多个设备的程序实例的映射。这个notification_key就是用来对所有注册ID已经和key关联的了的设备散发通知的令牌。更多和本话题相关的讨论,见User Notification。

通知键名(Notification Key Name)

用户通知特性的一部分。这个notification_key_name就是一个名字或者识别符号(可以被第三方程序用作用户名),用来区分是否对指定的用户是独一无二的。它被第三方用来对单独的用户的注册ID分组。更多和本话题相关的讨论,见User Notifaction。

 

生命周期流程

  • 开启GCM服务。手机上运行的一个Android程序注册以能够接收消息。
  • 用户通知。一个第三方服务器可以选择性的在一个notification_key中分组多个注册ID,来发送消息给一个用户的多个设备
  • 发送一个消息。一个第三方程序服务器发送消息给设备
  • 接受消息。一个Android程序从GCM服务器接收一个消息。

这些过程会在下面进行更详细的描述。

打开GCM服务

这是一个运行在已经注册了的手机设备上的Android程序接受消息时时间的顺序:

  1. 第一次Android程序需要使用消息服务的时候,它向GCM服务器发送一个注册的intent。

这个注册的intent(com.google.android.c2dm.intent.REGISTER)包含了发送者ID和程序ID。

注意:因为第一次运行的时候没有生命周期方法可以调用,所以注册的intent应该在onCreate()里发送,但是只能在程序没有注册的情况下。

  1. 如果注册成功,GCM服务器广播一个包含了注册ID和程序ID的com.google.android.c2dm.intent.REGISTRATION intent。

Android程序应该保存这个ID,后来会用来(例如,在onCreate()里检查是否已经注册了)。注意谷歌可能周期性的刷新注册ID,所以你在设计Android程序的时候,要明白com.google.android.c2dm.intent.REGISTRATIONintent 可能要被多次调用。你的Android程序需要能够给与相应的响应。

  1. 为了完成注册,Android程序向程序服务器发送注册ID。程序服务器一般就把注册ID保存在数据库中。

注册ID一直持续到Android程序自己注销掉,或者直到谷歌为你的Android程序刷新了注册ID。

注意:当用户卸载一个程序的时候,不会自动注销GCM。它只会在GCM服务器尝试发送消息到设备,设备反馈程序被卸载或者没有设置一个广播接收器接受com.google.android.c2dm.intent.RECEIVEintents的时候才会注销。在哪个阶段,你的服务器应该标识设备是注销了的(服务器将会获得一个未注销的错误)。

注意注册ID完全从GCM服务器删除可能需要好几分钟。所以如果第三方服务器这段时间发送消息,会获得一个有效的消息ID,即使这样消息还是不会发送给设备。

发送一个消息

程序服务器发送消息给Android程序的时候,下面的事情必须完成:

  • Android程序已经指定为一个消息的接受者。这个可能是下面中的一个:
    • 允许程序从一个特别的设备接受消息的一个单独的注册ID(或者一个数组的注册ID)
    • 一个notification_key或者相应的notification_key_name,用来映射一个用户到多个注册ID。更多关于本话题的讨论,见User Notifications。
  • 一个API key。这是开发者已经在程序服务器上为Android程序设置好的(更多的讨论,见第三方服务器的角色一节。现在能够发消息到设备了。

这里是程序服务器发送一个消息的事件顺序:

  1. 程序服务器发送一个消息到GCM服务器。
  2. 如果设备不在线谷歌把消息放入队列并存储。
  3. 设备上线的时候,谷歌发送消息给设备。
  4. 在设备上,系统通过有相应权限的intent广播发送消息给特别的Android程序,所以只有指定的Android程序才能获得消息。这将唤醒Android程序。在接收消息之前Android程序并不需要提前运行。
  5. Android程序处理消息。如果Android程序正在做非常重要的处理,你可能想要获取PowerManager.WakeLock,在服务里做任何处理。

一个Android程序能够在它不想接受消息的时候可以注销GCM。

接收消息

下面是一个设备上的Android程序接受消息的事件顺序:

  1. 系统获得到来的消息,如果有原生键值对的话,从消息载荷中取出。
  2. 系统把键值对作为一组extras传送给在com.google.android.c2dm.intent.RECEIVE Intent指定的Android程序
  3. Android程序根据键从com.google.android.c2dm.intent.RECEIVE Intent中提取原生数据,然后处理。

用户看到了什么

当手机用户安装了一个支持GCM的Android程序时,Google Play Store将会通知他们这个程序包含支持GCM。他们要想安装这个程序就必须得同意使用这个特性。

第三方程序服务器的角色

在那能够使用GCM这个特性写客户端Android程序之前,你必须得有一个满足一下条件的服务器:

  • 能够与你的客户交互
  • 能够发送对GCM服务器的HTTPS请求。
  • 能够处理处理请求或者根据需要使用二进制指数退避算法(exponential back-off)重新发送
  • 能够存储API key和用户的注册ID。每次发送消息的时候API key应该包含在发送POST请求的头部。

发送消息进行时

这张讨论第三方程序服务器如何发送消息到一个或者多个手机设备。注意一下几条:

  • 一个第三方程序服务器能够发送消息到一个单独的或多个设备。同时发送给多个设备的消息,被称为广播消息。
  • 为了发送给消息到一个单独的用户的多个设备,你可以使用notification_key,之前在User Notifications描述过。
  • 你有两种构造请求和回复的选择:纯文本或者JSON。
  • 然而,发送广播消息,你必须使用JSON,纯文本不行。

在第三方程序服务器能够发送消息给一个Android程序之前,必须获得这个程序的注册ID。

请求格式

为了发送消息,程序服务器发送一个到https://android.googleapis.com/gcm/send的POST请求。

消息请求由两部分组成:HTTP头(HTTP header)和HTTP体(HTTP body)。

HTTP头必须包含以下两个条目:

  • Authorization: key=YOUR_API_KEY
  • Content-Type: application/json for JSON; application/x-www-form-urlencoded;charset=UTF-8 for plain text.

例如

Content-Type:application/json
Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA

{
  "registration_ids" :["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
  "data" : {
    ...
  },
}

注意:如果Content-Type被声乐了,就默认以纯文本发送。

 

HTTP体内容取决于你是用JSON还是纯文本。对JSON来说,必须包含一个包含JSON对象的字符串,JSON对象中有以下字段:

字段

描述

registration_ids

保存一组接受消息的设备(注册ID)的字符串数组。包含至少一个最多1000个ID。为了发送一个广播消息,你必须使用JSON。为发送一个单独的消息到一个单独的设备,你可以使用包含一个注册ID的JSON对象,或者纯文本(见下面)。一个请求必须包含一个接收者—这个接收者可以是一个注册ID,一个数组的注册ID,或者一个notification_key。

notification_key

一个映射单独用户和多个和用户关联的注册ID的字符串。这允许第三方服务器发送一个单独的消息给一个用户多个程序实例(特别实在多个设备上)。第三方程序服务器能够把notification_key作为消息的目标,而不是注册ID(或者一组注册ID)。对notification_key来说允许的最大的成员数量是10.更多和本话题相关的讨论,见User Notifications。可选字段。

notification_key_name

一个指定用户独一无二的名字或者识别符号(可以被第三方程序用作用户名)。它被第三方用来对一个单独的用户的注册ID分组。如果对于一个项目ID你又多个应用程序的话,每个程序notification_key_name都是独一无二的。这保证了通知只会发送给预定的目标程序。更多的和本话题的讨论,见User Notifications。

collapse_key

当设备离线的时候,用来处理一组类似的消息的任意的字符串(如“可用更新”),这样之后最后的消息才能发送给用户。这是用来防止当用户在线的时候发送给手机太多的消息。注意因为发送消息的顺序是不保证的,所以最后的消息,并不一定是服务器最后发出的。见Advanced Topics for more discussion of this topic。可选字段

data

能够表示消息载荷数据中键值对的JSON对象。如果包含这个字段,载荷数据会被作为程序数据包含在intent里,key作为extra的名字。例如,"data":{"score":"3x1"} 会生成一个名字为score,value为3x1的intent。键值对的数量没有限制,但是消息的总体大小是有限的(4kb)。值可以是任何的JSON对象,但是我们建议使用字符串,因为GCM服务器总会把值变成字符串。如果你想包含对象或者其他非字符串的数据类型(如整型或布尔型),你只能自己转换了。还要注意key不能是一个保留字(任何以google开头的)。为了事情变得复杂一点,有一些保留字(如collapse_key)是允许在载荷数据中出现的。然而,如果请求也包含这个单词,请求中的这个值不会覆盖载荷数据中的值。所以不推荐使用这个表中的字段名,即使技术上是允许的。可选字段。

delay_while_idle

如果包含这个字段,表示如果设备不是空闲的,消息不应该立即发送。服务器一直等到设备活动状态,然后只有最后的一个对应collapse_key值的消息才会发送。可选字段。默认的值是false,但是必须是一个JSON布尔值。

time_to_live

如果设备离线的话消息会被曝存在GCM存储空间中多长时间(秒记)。可选字段(默认是4周,必须是一个JSON数据)。

restricted_package_name

包含你程序包名的字符串。如果设置了,消息只会发送给匹配包名的注册ID。可选字段。

dry_run

如果包含该字段,允许开发者在不发送消息的情况下测试请求。可选字段,默认值为false,必须是JSON布尔值。

如果你是使用的纯文本而不是JSON,消息的字段必须设置为HTTP体中的参数,而且他们的语法有些不同,如下:

字段

描述

registration_id

必须包含接受消息的设备的注册ID。必须字段。

collapse_key

和JSON一样(见前面的表)。可选字段

data.<key>

载荷数据,表示成有数据位前缀,key为后缀的参数。例如,一个参数data.score=3x1将会导致一个 extra名为score,key为3x1的字符串的intent。键值对参数数量没有限制,但是有消息总体大小的限制。还要注意key不能是一个保留字(任何以google开始的单词)。为了让事情变得稍微复杂,有些保留字(如collapse_key)技术上是允许的。然而,如果请求也包含该词,请求中的值不会覆盖载荷数据中的值。所以使用表中定义的字段是不推荐的,虽然他们技术上是允许的。可选字段。

delay_while_idle

当是真的时候,应该表示为1或者true,其他都是假。默认是假。

time_to_live

和JSON一样(见前面的表)。可选字段。

restricted_package_name

和JSON一样(见前面的表)。可选字段。

dry_run

和JSON一样(见前面的表)。可选字段。

如果你想测试你的请求(不管是JSON还是纯文本),而不像发送消息给设备,你可以设置一个可选的HTTP或JSON参数,dry_run,值为true。结果几乎和没有参数是一样的,除了消息不会发送给设备。最终,响应会包含消息的假ID和广播字段(见响应格式一节)。

请求举例

这是一个使用JSON最小的请求(只有接收者,没有任何参数的消息):

{ "registration_ids": [ "42" ] }

这是使用纯文本一样的示例:

registration_id=42

这是一个有6个接收者和载荷数据的示例:

{ "data": {
    "score": "5x1",
    "time": "15:10"
  },
  "registration_ids": ["4", "8", "15", "16", "23", "42"]
}

这是一个设置了6个接收者,还有一些可选字段的示例:

{ "collapse_key": "score_update",
  "time_to_live": 108,
  "delay_while_idle": true,
  "data": {
    "score": "4x8",
    "time": "15:16.2342"
  },
  "registration_ids":["4", "8", "15", "16", "23", "42"]
}

这是一个使用纯文本的同样的消息(只有一个接收者):

collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.score=4x8&data.time=15:16.2342&registration_id=42
  

注意:如果你的组织有防火墙,约束了互联网发送或接收消息,你应该配置一下以使GCM的连接是允许的,以便你的Android设备能够接收到消息。打开的端口为:5228,5229和5230。GCM一般只是用5228,但是有时候会使用5229和5230。GCM不提供特别的IP,所以你应该允许你的防火墙能够接收外部对IP地址的连接,这些IP地址在谷歌ASN15169的IP块中。

响应格式

当尝试发送消息时有两种可能的结果:

  • 消息被正确处理
  • GCM拒绝了请求

当消息被正确处理的时候,HTTP响应的状态码是200,而且HTTP体中包含了更多消息状态的信息(包括可能的错误)。当请求被拒绝的时候,HTTP相应包含一个非200的状态码(如400,401或503)。

下面的表总结了HTTP响应头可能包含的状态码,点击故障排解链接,查看解决各种类型错误的建议。

响应

描述

200

消息被成功处理。响应体包含更多关于消息状态的细节,但是格式要看是JSON还是纯文本。见成功请求说明一节,查看更多细节。

400

只对JSON请求适用。表明请求不能被解析为JSON,或者包含了不可用的字段(如,需要数值的时候传递一个字符串)。确切失败的原因在响应里,在重新请求之前,这个问题应该被处理。

401

验证发送者账户额时候有错误。故障排解。

5xx

状态码在500-599之间(如500或503)的错误表明GCM服务器当尝试处理请求的时候,或者服务器暂时不可用的时候(例如,超时),有内部错误。发送者必须过段时间再重新尝试,在响应里里加入任何稍后尝试的头。程序服务器必须实现二进制指数回避算法。故障排解

正确相应的说明

当一个JSON请求成功了(HTTP状态码200),响应体包含一个包含如下字段的JSON对象:

字段

描述

multicast_id

多发消息独一无二的标识(数字)。

success

处理时没有错误的消息的数量。

failure

不能被处理的消息的数量。

canonical_ids

包含一个典型注册ID的结果的数量。更多关于本话题的讨论见Advanced Topics

results

表示消息被处理消息状态的对象数组。对象顺序和请求的顺序一样(也就是说,对于请求中的每个注册ID,它的结果也在相应的同样的位置),他们有以下字段:

  • message_id: 表示消息被正确处理的字符串。
  • registration_id: 如果设置了该字段,意味着GCM处理了消息,但是设备还有另外的典型注册ID,所以发送者应该在将来的时候替代这个ID(或者他们可能会被拒绝)。如果请求有错误,该字段永远不会被设置。
  • error: 当为接收者处理消息的时候发生错误时,描述错误的字符串。可能的值和记录上面的表中一样,再加上“不可用”(表示GCM服务器忙,不能为该接收者处理消息,所以它就可以重新尝试请求)

如果错误的值和canonical_ids都是0,就没有必要解析响应其他的字段了。不然,我们建议你循环访问结果字段并对对象做下面的操作:

  • 如果设置了message_id字段,检查registration_id:
    • 如果设置registration_id字段,在你的数据库里使用新值(典型ID)替换原来的ID。注意原来的ID并不是结果的一部分,所以你需要从请求发送的registration_id中获取(使用相同的索引)。
  • 否则,获得错误的值:
    • 如果它是不可用的,你应该在其他的请求里重新尝试。
    • 如果它没有注册(NotRegistered),你应该从服务器数据库中删除该注册ID,因为程序从设备删除了或者没有配置一个广播接收器来接收com.google.android.c2dm.intent.RECEIVE intents。
    • 否则,请求中发送的注册ID有错误;可能是个无法恢复的错误,就需要从服务器数据库中删除注册。所有错误的值见错误响应说明一节有可能的错误值。

当一个纯文本的请求成功了(HTTP状态码200),响应体包含1或2行的键值对。第一行一般时可用的,他的内容一般是id=ID或者Error=GCM错误码。如果第二行有的话,个职位registration_id=canonicalID。第二行是可选的,而且知呢个在第一行没有错误的情况下发送。我们建议和处理JSON类似的方法一样处理纯文本相应:

  • 如果第一行以registration_id开始,检查第二行:
    • 如果第二行以registration_id开始,用它的值替换你服务器数据库中的注册ID。
  • 否则,获得Error错误:
    • 如果是未注册(NotRegistered),从服务器数据库中删除该注册ID。
    • 否则,可能是一个不可恢复的错误(注意:纯文本请求永远不会返回不可用的错误码,而是返回HTTP状态码500)。

错误响应的说明

这是处理发送消息到一个设备时可能出现的各种类型的错误的推荐方法。

缺少注册ID

检查确定请求包含注册ID(在纯文本消息的registration_id参数中或者JSON的registration_id字段中)

发生在错误码是MissingRegistration时。

不可用的注册ID

检查发送给服务器的注册ID的格式。确保和手机在com.google.android.c2dm.intent.REGISTRATIONintent接收到的注册ID匹配,没有截断或者添加字符。

发生在错误码是InvalidRegistration时。

不匹配的发送者

和一个特定的发送这组绑定的注册ID。当一个程序注册了GCM,它必须指定哪个发送者是允许发送消息的。确保你发送消息到设备时用的是这其中的一个。如果你切换到不同的发送者,已经存在的注册ID不可用。

发生在错误码为MismatchSenderId时。

未注册的设备

一个已经存在的注册ID在以下情况可能是不可用的:

·        程序自己通过发送com.google.android.c2dm.intent.UNREGISTERintent注销了。

·        程序自动注销了,这可能会发生(不保证)在用户卸载程序的时候。

·        注册ID到期了。谷歌可能会刷新注册ID。

·        程序更新,但是新版本的没有配置广播接收器接受com.google.android.c2dm.intent.RECEIVEintents。

对于以上所有的例子,你应该从第三方服务器中删除注册ID,并且停止使用它发消息。
发生在错误码为NotRegistered时。

消息太大

消息中载荷数据的总体大小不能超过4096字节。注意这个同时包含键值的大小

发生在错误码为MessageTooBig时。

不可用的数据键(key)

载荷数据包含一个键(如任何以google为前缀的值),被GCM内部使用在com.google.android.c2dm.intent.RECEIVE Intent 中,不能被使用。注意一些单词(如collapse_key)也被GCM使用,但是允许在载荷数据中使用,这种情况下载荷数据值会被GCM值覆盖掉。

发生在错误码为InvalidDataKey时。

不可用的存活时间

存活时间字段的值必须是一个整型,表示从0到2,419,200(4周)之间一个持续时间。

发生在错误码为InvalidTtl时。

验证身份错误

用来发送消息的发送者账户不能被验证。可能的原因:

·        验证头部丢失或者语法错误

·        设置的key是不可用的项目编号

·        Key可用但是GCM服务不可用

·        从服务器发起的请求不在服务器Key IP的白名单里。

检查发送时验证头部的标记,你的项目编号关联的API是否正确。你可以运行下面的命令来检测你的API key是否可用:

# api_key=YOUR_API_KEY
# curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send  -d "{\"registration_ids\":[\"ABC\"]}"

如果你收到了401的HTTP状态码,你的API key不可用。否者你应该看到类似下面的结果:

{"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}

如果你想确定注册ID的可用性,你可以替换把"ABC"替换成注册ID。

发生在HTTP状态码为401时。

超时

服务器不能即时的处理请求。你因该重试相同的请求,但是你必须遵守一下要求:

·        如果没有被包含在GCM服务器返回的响应里,加上Retry-After的头。

·        在你的重试机制中实现二进制指数退避算法。这意味着每次重试失败之后,以指数方式增加延时(例如,如果你第一次等待了1s,然后第二次等待至少2s,然后4s,继续下去)。如果你在发送多发消息,使用一个额外随机的数量分别对每个延时,防止同时又产生一个对所有消息的请求。

引起问题的发送者可能会被列入黑明白

发生在HTTP状态码为501到599之间时,或者在结果数组里的JSON对象的错误字段不可用时。

服务器内部错误

当尝试处理请求的时候,服务器晕倒了错误。你应该重试相同的请求(遵循超时一节里的要求),但是如果一直错误,请向android-gcm组报告错误。

发生在HTTP状态为500,或者结果数组中的JSON对象错误字段为InternalServerError时。

不可用的包名

消息发送给一个注册ID时,它的包名和请求中传递的值不匹配。

发生在错误码为InvalidPackageName时。

响应举例

这节展示了几个被成功处理的消息的相应的实例。见请求举例,响应的示例基于请求示例:

这是一个发送给一个接收者的JSON消息示例,响应中没有canonical ID字段:

{ "multicast_id": 108,
  "success": 1,
  "failure": 0,
  "canonical_ids": 0,
  "results": [
    { "message_id": "1:08" }
  ]
}

或者请求是纯文本的格式:

id=1:08

这是发送给6个接收人(ID分别为4,8,15,16,23和42)的消息成功诶处理后的响应。1个 canonicalregistration ID 返回,还有3个错误:

{ "multicast_id": 216,
  "success": 3,
  "failure": 3,
  "canonical_ids": 1,
  "results": [
    { "message_id": "1:0408" },
    { "error": "Unavailable" },
    { "error": "InvalidRegistration" },
    { "message_id": "1:1516" },
    { "message_id": "1:2342", "registration_id": "32" },
    { "error": "NotRegistered"}
  ]
}

这个例子中:

  • 第一个消息:成功,不需要请求了。
  • 第二个消息:应该重发(发给注册ID8)。
  • 第三个消息:有不可恢复的错误(可能数据库中的值被破坏)。
  • 第四个消息:成功,不需要请求了。
  • 第五个消息:成功,但是注册ID应该在服务器数据库中更新(从23到32)
  • 第六个消息:注册ID(42)应该从数据库中删除,因为程序从设备卸载了。

或者如果上述第四个使用纯文本发送的消息:

Error=InvalidRegistration

如果上述第五个消息也是使用纯文本发送的:

id=1:2342
registration_id=32

查看统计

为了查看GCM程序的统计或者其他错误信息:

  1. 打开谷歌开发者控制台
  2. 登录开发者账户。

你将看到你所有程序列表页。

  1. 点击你想查看GCM状态的程序的旁边“统计”链接。

现在你在统计页面了。

  1. 点击下拉菜单,选择你想查看的GCM统计。

注意:谷歌API控制台的状态对GCM不可用。你必须使用开发者控制台。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenSSL is a widely-used open-source cryptographic library that provides support for various cryptographic algorithms, including the GCM (Galois/Counter Mode) encryption mode. GCM is an authenticated encryption mode that provides both confidentiality and integrity. It combines the Counter (CTR) mode of encryption with a universal hash function called Galois Message Authentication Code (GMAC). GCM is commonly used for secure communication protocols like TLS. To use GCM with OpenSSL, you can utilize the EVP (Envelope) API provided by OpenSSL. Here's an example of how you can use OpenSSL to perform GCM encryption and decryption: ```c #include <openssl/evp.h> void encrypt_decrypt_gcm(const unsigned char* key, const unsigned char* iv, const unsigned char* aad, const unsigned char* ciphertext, int ciphertext_len, unsigned char* tag, unsigned char* plaintext) { EVP_CIPHER_CTX* ctx; int len; int plaintext_len; // Create and initialize the context ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); // Set the key and IV EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_LEN, 256, NULL); EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv); // Set the AAD (Additional Authenticated Data) EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)); // Perform the encryption EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len); // Finalize the encryption (generates the authentication tag) EVP_EncryptFinal_ex(ctx, ciphertext + len, &len); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag); // Cleanup EVP_CIPHER_CTX_free(ctx); } int main() { unsigned char key[32]; // 256-bit key unsigned char iv[12]; // 96-bit IV unsigned char aad[16]; // Additional Authenticated Data unsigned char ciphertext[128]; unsigned char tag[16]; unsigned char plaintext[128]; // Initialize the key, IV, AAD, and plaintext encrypt_decrypt_gcm(key, iv, aad, ciphertext, sizeof(ciphertext), tag, plaintext); return 0; } ``` In this example, you would need to replace the placeholders for the key, IV, AAD, ciphertext, and plaintext with the actual data you want to use. Additionally, make sure to include the necessary OpenSSL headers and link against the OpenSSL library when compiling. This is just a basic example and it's important to use proper cryptographic practices and ensure the security of your implementation. It's recommended to refer to the OpenSSL documentation and consult cryptographic experts for more guidance on using GCM with OpenSSL.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值