作者: 邓明轩
前言
数据推送 是 Bla ck Be rry 应 用平台 的一 大优 势, 在 Bla ck Be rry 应用 平台 上部 署的 应用可 以
和 Bla c kBe rr y 推 送邮 件一 样通过 推送 实时 地将 数据 从服务 器端 推送 到 Bla ck Be rry 手持 设备 端。所 以, 对于 很多 应用 开发商 而言 , Bla c kBe rry 应 用平台 提供 的推 送功 能是 Bla ck Be rry 应 用集成 必然 会使 用到 的强 大功能 。
然而, 因为 种种 原因, 有 一些开 发商 发现使 用 Bla ck Berr y En t e rpris e S e r ve r ( BE S ) 应 用平
台的推送功 能并不能保证数据到 达 Bla c kBe rry 设备,导致应用 层面的种种问题。实际上 , Bla ck Be rr y 应 用平 台提 供了 从多机 制保 证数 据推 送的 成功, 只要 我们 充分 了解 BE S 中 MD ( S 以 下简 称 MDS ) 的推 送机制 , 我们 就可 以利 用平 台提 供的机 制保 证数 据到 达 Bla ck Be rry 手持 设 备。
本章节 的主 要目 的是 详细 分析 MD S 的推 送机 制,让 读者更 好地 了解 Bla c kB er r y 应用 平 台,从 而可 以开 发更 加强 壮,更 加稳定 的 Bla ck Be rr y 应 用。
值得读 者注 意的 是, 本章 节的内 容是 结合 少量 的官 方文档 , 配 合于 大量 的测 试总结 而来 的, 旨在 为读 者提 供更多 的线索 以理 解 MD S 推送机 制。 如果 本章 节的 内容 与 RIM 提 供的 任 何官方 文档 有冲 突的 话请 以官方 文档 为准 。 同 时, 不同版本 的 Bla ck Be rry 手 持设备 在不 同场 景下也 可能 有不 同的 行为 , 所以 读者 在生 产环 境实 施 Bla ck Be rry 应用 时也要 结合用 户所 使用
的 Bla ck Be rry 设备 进行测 试,才 能最 好地 保证 应用 的稳定 性。
MDS 推送 介 绍
M DS 推送架构
在详细讲 解 MD S 推送 机制 之前我 们先 从整 体上了 解 MD S 推送 的架 构, 下面 是 MD S 推 送架构 的示 意图 :
从示意 图中 可以 看到 在 Bla ck Be rry 应用 平台 上的 数据 推送从 整体 上可 以分 为六 步, 按 时 间顺序 分别 为:
1 . 第一步 : 应 用服 务器 向 MD S /BE S 服务 器发 送推 送请求 , 所发 送的 请求 为 H T TP 格 式的请 求,有 关请 求的 详细 格式 在下一 小节 中有 详细 讲解 。
2 . 第二步 : MDS / BE S 服 务器 查询相 关配 置数 据库 , 确 定应用 服务 器所 发送 的请 求是否 为合 法的请求 。 此 外, M DS /BE S 服务器 还会 根据 资源情 况确定 是否 接收 该请求 。 对于是 否接 收请求 的判 断在 下一 节内 容中也 有详 细讨 论。
3 . 第三步 : MDS / BE S 服 务器 向应用 服务 器返 回消息 , 通知应 用服 务器 是否 接受 该请求 。 返 回消息 以 HT TP 答复的 方式 返回给 应用 服务 器。
4 . 第四步 : MDS / BE S 服 务器 将数据 推送 到手 持设 备端
5 . 第五步 :手 持设 备端 对数 据进行 处理后 向 MDS /BE S 服务器 返回 确认 消息
6 . 第六步 : MDS / BE S 根 据手 持设备 端返 回的 消息 决定 向应用 服务 器返 回什 么异 步消息 , 这 一步并 不是 必然 发生 的, 根据推 送请 求的 不同 有可 能不发 生。 从这里 我们 可以 看到 , 从应 用服务 器到 手持 设备 端的 推送通 道是 由多 个不 同的 通道连 接
而成的 , 这其 中有很 多个 连接点 , 某一 个连接 点出 现异常 都可 以导 致推 送的 失败 。 所 以应 用 开发商 需要 详细 了解 这些 连接点 可能 出现 的问 题, 在应用 开发 过程 中进 行规 避。
在详细 描述 各个 可能 出现 问题的 关键 点之 前, 需要 先了解 推送 的基 本实 现。 对于应 用开 发人员 而言 , 完 成数 据推 送需要 完成 的主 要程 序编 写工作 有: 应用 服务 器端 发出推 送请 求的 程序 , 手 持设 备端侦 听接 收推送 数据 的程 序, 和服 务器端 侦听 接收 确认 消息 的程序 , 如下 图 橙色框 图所 显示 的:
以下章 节将 对这 三个 部分 作详细 讲解 。
数据推送命令 格式
在 Bla ck Be rry 应用 平台上 的数据 推送 是由 应用 服务 器发起 的, 应用 服务 器根 据应用 逻辑 进行判断 , 发 现有 数据需 要推送 到用 户的 手持 设备 端时连 接 MDS / BE S 服 务器 进行数 据推 送。 应用服 务器 与 MDS / BE S 服 务器的 连接 方式 为 HTTP 连接, 通过 HT TP 连 接发 送一个 P OS T 请 求,将 需要 推送 的数 据作 为 P OS T 的内 容。
该 P OS T 请求 的 U RL 格式 为:
h t t p:// BE S _ HOS T : BE S _P O R T / pus h?DE S TINA TIO N= D E S INT A TIO N _ADD RE SS &P OR T = HA NDHE L
D_APP LIC A TIO N _P ORT &RE Q U E S TU RI=/
下面是 请求 中各 参数 的说 明:
参数 |
描述 |
BE S _H OS T |
Bla ck Be rry En t er p ris e S e r v er 的服 务器 名或 者是 IP |
BE S _P OR T |
Bla ck Be rry En t er p ris e S e r v e r 的 推送 端口 ,一 般是 8 08 0 |
DES TINA TIO N_ A DDRE S S |
用户的 邮件 地址 或者 是设 备码 ( P IN) |
HAN DHEL D_APP LI C A TIO N_ P OR T |
Bla ck Be rry 手 持设 备需要 帧听的 端口 |
也就是说 , 应 用服 务器通 过 BE S _ HOS T 和 BE S _ P OR T 指定需 要连接 的 MDS /BE S 服务器 和
需要连 接的 端口 。 BE S 服 务器安 装后 缺省 使用 8 08 0 作为 推送 端口 ,所 以推 送应用 开发 人员 一般情 况下 只需 要了 解 M DS /BE S 服 务器 的服 务器名 或者 是 IP 地址 就可 以了。 如果 BE S 管理 人员在 安装 服务 器后 修改 过推送 端口 ,则 需要 告知 开发人 员使 用新 指定 的端 口。
推 送 U R L 中 pus h? 后面 的 部分用 于 指定 数 据的接 收 者和手 持 设备 需 要帧听 的 端口 。 DES TINA TIO N_ A DDRE S S 用 于指定 数据 的接 收者 , 可以 使用该 用户 的邮 件地 址或 者是该 用户 手 持设备 的 P IN 码。 HA NDHE LD_APP LIC A TIO N _P OR T 用 于指定 手持 设备 需要 帧听 的端口 ,这 里 使用的 端口 只是 一个 约定 ,要求 在手 持设 备上 运行 的程序 从这 一端 口中 读取 数据。
除了 U R L 参 数以 后, 在推 送过程 还可 以使 用一 些规 定好 的 HTTP 头 指定该 推送 的属性 ,
HT TP 头 参数 表如 下:
HT T P 头 |
描述 |
X - RIM-P us h-ID |
用于指 定该 消息 的 ID , 该 I D 需要 是一 个唯 一值 , 可 以用于 取消推 送或 者是 查看 推送 的状态 。 |
X - RIM-P us h-N ot ifyU RL |
用于指 定确 认消 息的接 收 U RL 。 |
X - RIM-P us h-R eli ab i lit y -Mo d e |
用于指 定推 送的 可靠 性。 |
X - RIM-P us h-D eli v er - Be f o r e |
用于指 定推 送数 据的 最迟 推送时 间。 |
X - RIM-P us h-P rio rit y |
用于指 定推 送数 据的 优先 级。 |
X - RIM-P us h-ID 属性 一般建 议使 用 U R L 和 编号 结合的 方式, 如 1 2 3 @ bl ac kb er r y .c o m 。为
了更好 地控 制数 据的 推送 ,一般 不建 议使 用随 机数 作为推 送 ID 。使 用统 一的 I D 生成 方式 更 有利于 推送 数据 的取 消和 状态确定 。 注意 , 如 果没有 指定该 参数 的话 , MDS /BE S 服务器 会自 动生成 一个 唯一 的 ID ,这 样就无 法在 应用 服务 器上 使用这 个 ID 对特 定的 推送 数据进 行处 理 了。此 外, 推 送 ID 不 能以 @ ppg .rim .c o m 结 束。
X - RIM-P us h-N ot ifyU RL 属 性 通 过 U RL 的 形 式 指 定 了 确 认 消 息 的 接 收 地 址 , 如 h t t p://t e s t ings er v er: 7 7 7 8 。 指定了 这一 属性后 , MDS / BE S 服务 器会 将推 送的确 认消息 以 HT TP 请求的 形式 发送 到指 定的 服务器 。 也 就是 说应 用开 发者需 要开 发一 个 HT TP 服 务器端 程序 监 听指定 服务 器的 指定 端口 (上例中 则是 服务 器 t e s t in gs er v er 的 7 7 7 8 端口) , 通 过这个 服务 器 端程序 获取 确认 消息 。 在 确认消 息中 会包 含 HT TP 头 X -RIM -P us h-ID 和 X -RIM- P us h-S t a t us , 通
过 X - RIM-P us h-ID 告知 监听 者是哪 条推 送数 据的 确认 消息,通 过 X - RIM-P us h-S t a t us 指明该 数 据推送 的结 果, 20 0 代表 推送成 功, 40 0 代 表推送 失败。 现实 环境 中对 于数 据推送 是否 成功
不能简 单地 以结 果 20 0 或 者是 4 0 0 进行 判断 , 需要 结合很 多因 素进 行判断 , 本文的 后续 章节 会详细 描述 。
属性 X - RIM-P us h-R eli ab i lit y -Mo de 用 于指 定推 送的 可靠 性, 值 可以 是 T RA NSP OR T 或者是 APP LIC A TIO N , 另外 有一个 值 APP LIC A TIO NP REF ER RED 涉及更 复杂 的场景 , 这里 不做描述 。 如 果指定 可靠 性为 TR ANSP O R T 则 以数 据到 达手 持设备 准,本 文称 之为 非应 用依 赖。如 果指 定 可靠性 为 APP LI C A TIO N 则 以数据 被手 持设 备端 应用 接收为准 , 本 文称 之为应 用依赖 。 对于 不 同可靠 性设置 , 本文 的后 续章节 会有 详细 描述 。 总 体而言 , 非应 用依赖 的推 送更适 合于广 播 性质的 不要 求应 用一 定收 到数据 的场景 , 而 应用 依赖 更适合 于点 对点 的要 求应 用一定 要收 到 数据的 场景
属性 X - RIM-P us h-Deli v er - Bef o r e 用于 指定 数据 推送的 最后时 间, 如果 在指 定时 间前该 数 据仍无 法被 成功 推送 到手 持设备 端, 则该 数据 会被 视作过 期而 被 MDS / BE S 服 务器丢 弃。
属性 X -RIM -P us h-P rio rit y 用 于指定 推送 数据 的优 先级 ,指定 推送 数据 的优 先级 并不能 加 快数据 的推送 , 指 定优 先级 的结果 是推 送数 据到 达手 持设备 端的 行为 不同 。 可以 选择的 值有 : no ne ( 缺省 ) , lo w , m e di u m 和 hig h 。如果 指定 优先 级为 lo w , m e di um 或 者是 hig h ,则 用 户只是 接收 到数 据, 如果 指定优 先级 为 hig h , 则用 户在接 收到 数据 后还 会看 到提示对话框 。
数据推送关键 代码
理论上讲 , 应 用服 务器的 数据推 送代 码可 以用 任何 可以提 供 HT TP 支持的 语言 编写 , 需 要实现 的不 过是通 过 HTTP 协议往 指定 的服 务器 和端 口发 送 P OS T 消息 。
下 面 以 ja v a 代码 为 例讲 解 数据推 送 的关键 代 码部 分 。本例 的 代码片 段 为一 个 Ja v a App li ca t io n 的部分 代码, 该 Ja v a App li ca t io n 在服务 器上 以 J 2 S E 应用 的形 式运 行,启 动一 个 线程发 送 HT TP 的 P OS T 请 求。以 下代 码为 该线程 的 r un 函数 :
public void run() {
Random random = new Random();
String pushId = "pushID:" + random.nextInt(); String data = "What need to be pushed" ;
try {
URL _pushURL = new URL( "http" , "testingBE S.abc.com" , 8080,
"/[email protected]&PORT=55100&REQUESTURI=/" );
HttpURLConnection conn = (HttpURLConnecti on) _pushURL.openConnection();
conn.setDoInput( true ); conn.setDoOutput( true ); conn.setRequestMethod( "POST" );
conn.setRequestProperty( "X-RIM-PUSH-ID" , pushId);
conn.setRequestProperty( "X-RIM-Push-NotifyURL" ,
"http://testingserver:7778" );
conn.setRequestProperty( "X-RIM-Push-Reliability -Mode" ,
"APPLICATION" );
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.close();
InputStream ins = conn.getInputStream();
int contentLength = conn.getContentLength();
int responseCode = conn.getResponseCode(); System. out .println( "Response Code is:" + responseCode);
if (contentLength > 0) {
byte [] someArray = new byte [contentLengt h]; DataInputStream dins = new DataInputStream(ins); dins.readFully(someArray);
System. out .println( new String(someArray));
} else {
System. out .println( "Content legth of response is 0" );
}
conn.disconnect();
} catch (IOException e) { System. err .println( "Exception:" + e);
}
}
在以上 代码 中, 先通 过 U R L 类建 立一 个 H T TP 连 接定 义, U RL 类的 构造 函数中 第一个 参 数 为协议 类型, 这里使 用“ h t t p ” ,第二 个参数 为服务 器名, 第三个 参数为 请求 的端口 号。 第二个 参数 和第 三个 参数 对应了 数据 推送 请求中 的 BE S _H OS T 和 BE S _P OR T 属 性。 U R L 类的 构造函 数中 第四 个参 数为 相对 U R L , 推 送属 性 DES TI NA TIO N 和 P O R T 都放在相 对 U RL 中, 代 码如下 :
URL _pushURL = new URL( "http" , "testin gBES.abc.com" , 8080,
"/[email protected]&PORT=55100&REQUESTURI=/" );
建立 了 U R L 类 的实 例后, 可以通 过该 实例 的 o p enCo nn ect io n 函数 打开 连接, 返回的 是 一个 Ht t pU RL Co nn ect io n 实 例。
HttpURLConnection conn = (HttpURLConnecti on) _pushURL.openConnection();
打开 h t t p 连 接后 可以 通过 连接实例 的 s et R eq ues tP r o p e rt y 函数 设置 h t t p 头 , 推 送请求 中
的 h t t p 头属 性在 这里 设置 ,如:
conn.setRequestProperty( "X-RIM-PUSH-ID" , pushId);
其中一 个关键 的 h t t p 头属 性是 X - RIM-P us h-R eli ab i lit y -Mo de , 设 置该 属性 为 “ TR AN SP OR T ” 表示该推送是非应用依赖的推送,设置该属性为“ A PP LIC A TIO N ”表示该推送 是应用依赖的
推 送 。 两 者 的 具 体 区 别 在 后 面 的 章 节 会 有 详 细 的 讨 论 。 以 下 代 码 设 置 该 属 性 为
“ APP LIC A TIO N ”:
conn.setRequestProperty( "X-RIM-Push-Reliability -Mode" ,
"APPLICATION" );
特别要 注意 , 如 果设 置推 送类型 为应 用依 赖, 对于 服务器 的设 置和 手持 设备 有特定 的要 求。 一方 面是 服务 器端必 须是 4 .0 以上 , 同时 必须设 置允许 对所 使用 的端 口进 行应用 依赖 的 推送, 一方 面是 要手 持设 备的 R OM 版本 也是 4 . 0 以 上,同 时服 务器 必须 知道 手持设 备能 否 支持应 用依 赖的 推送 。 对于 服务器 的端 口设置 , 设 置界 面如下 , 可以 由 BE S 管理员 进行设 置:
如 果是 使用开 发环境 的 M DS -CS 模 拟器模 拟应 用依赖 推送 的话, 需要修 改 开发 环境 的 MDS /c o n fig 目录中 的 rim pu bl ic .p r o pe rt y 文 件, 去 除 pus h. ap pl ic a t io n. r eli ab le.po rt s 一行的 注释 , 同时加 上需 要推 送的 端口 ,如“ pus h. ap pl ic a t io n. r eli ab le.po rt s =1 0 0 , 5 5 1 0 0 ” 。
对于服 务器 端是 否知 道手 持设备 端的 版本 , 需 要通 过手持 设备 端的 操作 完成 。 只要 手持 设备端的 浏览器 通过 BE S 访问过网 络,服 务器就会 记录该手 持设备 是否支持 应用依赖 的推 送。 如果 只是 测试的话 , 在测试 前通 过手 持设 备端 的浏览 器打 开任 何一 个网 站就可 以了 。 如 果是生 产环 境, 则需 要考 虑客户 端应 用在 第一 次启 动的时 候主 动访 问一 次网 络, 以 保证 客户 端都可 以正 常接 收应 用依 赖的推 送。
如果以 上设 置没 有完 成的 话,对 MDS /BE S 服务 器发 送应用 依赖 的推 送时 会被 拒绝, 服 务器端 会出 现“ The s peci fi e d del iv er y m et ho d is no t p oss i bl e ”的错 误。 应用服 务器的 推送 程 序则会 捕获 以下 异常 :
“ java.io.IOException : Server returned H TTP response code: 4 00 for
URL: http://app... ”
设置属 性后 就需 要获 取 h t t p 连接的 Out putSt re am , 将 需要推 送的 数据 写入 Out p ut St re am
中,写 完后 关闭 连接 。
需要注 意的 是 MDS / BE S 服 务器是 否接 收该 推送 请求 是通过 h t t p 返 回码 实现的 ,所以 推 送应用 中需 要获取 到 h t t p 连接的 返回 码, 通过 返回 码判断 推送 是否 成功 ,代 码如下 :
int responseCode = conn.getResponseCode();
客户端接收关 键代 码
客户端 数据 接收 程序 运行 在 Bla ck Be rry 手持 设备 上, 必须通 过 ja v a 语 言实 现, 需要调 用
Bla ck Be rr y 设 备端 的 AP I 。
客户端 接收 程序 的主 体就 是启动 一个 线程 ,开启 h tt p:// : <po rt> 连接 (其中 po r t 是客户 端需要 侦听 的端 口号 ) ,然 后从该 连接 中获 取 In putSt r e am ,从 In putSt re am 中获 取服务 器所
推送的 数据 。
下面是 侦听 线程 的 run 方 法,为 保持 程序 的完 整, 代码中 使用 到的 类属 性并 没有修改 ,
从 该 函 数 中 看 到 的 本 函 数 没 有 定 义 的 变 量 都 是 该 类 的 类 属 性 。 有 关 完 整 代 码 , 请 参 考
Bla ck Be rr y 开 发环 境所 提供 的标准 样例 。
public void run(){ StreamConnection stream = null ;
InputStream input = null ; MDSPushInputStream pushInputStream= null ;
while (! _stop )
{
try
{
synchronized ( t his )
{
_notify =
(StreamConnectionNotifier)Connector. open ( "http://:55100" );
}
while (! _stop )
{
stream = _n o ti fy .acceptAndOpen();
try
{
input = stream.openInputStream();
pushInputStream= new
MDSPushInputStream ((HttpServerConnection)stream, input); DataBuffer d b = new DataBuffer();
byte [] data = new byte [256];
int chunk = 0;
while ( - 1 ! = (c hu nk = i np ut .r ea d( da ta )) )
{
db.write (data, 0, chunk);
}
pushInputStr eam.accept(); input.close( ); stream.close ();
data = db.ge tArray();
}
catch (I OE xc ep ti on e 1)
{
System. er r .println(e1.toString());
if ( in pu t != null )
{
try
{
in pu t. cl os e( );
}
ca tc h (IOException e2)
{
}
}
if ( st re a m != null )
{
try
{
st re am .c lo se () ;
}
ca t ch (IOException e2)
{
}
}
}
}
_notify .close() ;
_notify = null ;
}
catch (IOExceptio n ioe)
{
if ( _notify != null )
{
try
{
_notify .c lo se () ;
_notify = null ;
}
catch ( IO Ex ce pt io n e )
{
}
}
}
}
}
以上代 码中 ,建 立端 口侦 听的代 码如 下:
_notify = (StreamConnectionNotifier)Connector. open ( "http:// :55100" ); 其中 U RL “ h t t p:// : 5 5 1 0 0” 是用于 侦听 推送 的特 定格 式, 5 5 1 0 0 为 需要 侦听的 端口。 两 个线程 不能 同时 打开 同一 个端口 的侦听 , 所 以在这 里使用 了 s ync h r o ni z e d 对 线程并 发进 行了
控制。
建立侦 听后 可以 通过函 数 ac cept And Op en 开 始侦 听, 当线程 调用 该方 法开 始侦 听的时 候 线程会 阻塞 在这 里, 直到 有推送 消息 到达 。代 码如 下:
stream = _notify .acceptAndOpen();
侦听之 后的 代码 为获 取连 接的 In putSt r e am , 从 In putSt re am 中获 取服 务器 端推送 的数据 。 读取完 数据 后关 闭 In putSt r e am 和 St re am Co nn ect io n ,然后 重新 调用 ac c ept A dn Op en 继续 侦 听端口 ,准 备接 收新 的推 送数据 。
开 发 人 员 如 果 希 望 使 用 应 用 依 赖 的 推 送 , 在 客 户 端 必 须 将 In putSt re a m 转 换 成 MDSP us hI np ut St re am , 同 时在接 收完 数据 后调 用 M DSP us hI np ut St re am 的 ac ce pt 函数 造知服 务器该 数据 已收到 。 这 也是 应用依 赖和 非应 用依 赖在 代码实 现层 面的 最主 要区 别。 代码如下 :
pushInputStream= new
MDSPushInputStream ((HttpServerConnection)stream, input);
……
pushInputStream.accept();
从良好的编程习惯来 讲 ,在连接使用后需要 主 动关闭所使用的连接 和 资源, 如 In putSt re am 、 St re am Co nn e ct io n 、 St re am Co nn ect io nN ot ifi er 等 。所 以在 样例代 码中也 可以 看 到该样例在 异常处理阶 段都对这些资 源进行了关 闭操作。在关 闭这些连接 和资源的时 候对 St re am Co nn ect io nN ot ifi er 需要特 别注 意, 有可 能在 St re am Co nn ect io nN ot ifi er 中会保 留有 未 读取的 推送 数据 , 需 要调 用 ac ceptA dn Op en 函 数将 保留 的数据 读取 出来 , 直 到 ac ce ptA dn Op en 处于阻 塞状 态。
另外 , 如 果使 用了 应用依 赖的推送 , 客 户端 程序调 用 MDSP us hI np ut St re am 的 ac ce pt 函 数后确 认消 息不 会马 上发 出, 而 是在 对应 用 In putSt r e am 和 St r e am Co nn ectio n 关 闭后才 发出 。 所以对 于应 用依 赖的 推送 ,保 证 In putSt re am 和 St r e am Co nn ect io n 的关 闭非常 之重要 。
异步确认消息 接收代 码
异步消 息的 接收 代码 运行 在服务 器端 , 在 推送 请求 的 X -RIM -P us h-Not ifyU RL 属 性所指 定 的服务 器上 侦听 指定 端口 。 和应 用服 务器 端的 数据 推送代 码一 样, 异步 确认 消息的 接收 程序 可以通 过任 何支 持 HTTP 的 语言编 写。 主要 的工 作是侦 听指定 端口 , 从 指定 端口获 取 MDS /BE S 发送回 来的 确认 消息 ,根 据 HTTP 协 议获 取相关 属性 并返回 相关 信息 。
下面 以 ja v a 代码 为例 对关 键代码 进行 说明 。 这 段代 码一 个 ja v a App li ca t io n 的一部分 , 是 侦听线程 的 run 函数 。
public void run() {
try {
System. out .println( "Waiting for notifica tion on port" + 77 78
+ "..." );
while ( true ) {
ServerSocket serverSocket = new ServerSocket(7778);
serverSocket.setSoTimeout(12000 0);
try {
Socket clientSocket = serverSocket.accept();
InputStream input = clientSocket.getInputStream(); StringBuffer str = new StringBuffer();
int byteRead = input.read();
while ((byteRead != - 1) && (i np ut .a va il ab le () > 0) ) {
str.append(( char ) byteRead);
byteRead = input.read();
} System. out .println(str.toString());
OutputStream output = clientSocket.getOut putStream();
String response = "HTTP/1.0 200 OK" ;
output.write(response.getBytes( ));
output.flush();
output.close();
input.close();
clientSocket.close();
} catch (SocketTimeoutException ste) { System. out .println( "Notification connection timeout.
Restarting..." );
}
serverSocket.close();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
异步确 认消 息的 接收 代码 比较简 单, 基本 上就 是打 开一个 So ck et 侦 听指 定的 端口, 本 例中 是 7 7 7 8 , 然后 不断地 从该端 口读 取数 据,打 开 So ck et 侦听 的代 码如 下:
S er v er So ck et s e r ve rSo ck et = new S e r ve rSo ck et ( 7 7 7 8 ) ;
在异 步 消 息 接收 过 程 中需 要注 意 的 是 接 收 完 MDS /BE S 服务 器 的 确 认 消 息 后 ,应 该 给 MDS /BE S 服 务器 返回 一个 2 0 0 的成 功消 息, 否 则 MD S /BE S 服 务器 会认 为发 送确 认消息 失败 , 可能重 次几 次后 再放 弃, 这样异 步消 息接 收程 序有 可能重 复收 到同 一条 确认 消息。 返回 成 功
消息的 代码 如下 :
OutputStream output = clientSocket.getOut putStream();
String response = "HTTP/1.0 200 OK" ; output.write(response.getBytes()); output.flush();
output.close();
BlackBerry SDK下载
相关链接:
BES服务器推送机制分析(一)
BES服务器推送机制分析(二)
BES服务器推送机制分析(三)