【发布时间】:2012-01-09 14:08:26
【问题描述】:
我已经实现了 c2dm,并且设备可以正常接收消息和所有内容。 但是有一个问题我找不到解决方案。
当某个事件发生时,我想将相同的消息快速推送到几千台设备,最好在一分钟内。我知道无法确定消息是否会送达,而且 Google 可能会因不同情况延迟消息。
除了发送部分,我的 iOS 实现大致相同。 15000 条消息大约需要 5 秒。向 Android 发送 5000 条消息需要一个多小时。
有人知道加快速度的方法吗? 还是 Google 会停止这种大规模推送以阻止垃圾邮件?
代码的 C2DM 部分如下。这是在 PHP 中,但我在阅读大多数其他编程语言时没有问题。 我使用脚本 connect() 一次,然后循环所有令牌并使用 sendMessage() 发送每条消息。发送完所有消息后,它会断开连接()。
<?php
class C2DMclient
{
private $authKey = NULL;
private $ch = NULL;
function connect() {
$post_params = array(
'Email' => 'C2DM_USER',
'Passwd' => 'C2DM_PWD',
'accountType' => 'HOSTED_OR_GOOGLE',
'source' => 'appname',
'service' => 'ac2dm',
);
$first = true;
$data_msg = '';
foreach($post_params as $key => $value) {
if($first)
$first = false;
else
$data_msg .= '&';
$data_msg .= urlencode($key).'='.urlencode($value);
}
$x = curl_init('C2DM_CLIENTLOGIN');
curl_setopt($x, CURLOPT_HEADER, true);
curl_setopt($x, CURLOPT_POST, true);
curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg);
curl_setopt($x, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($x);
curl_close($x);
$pos = strpos($response, 'Auth=');
$this->authKey = trim(substr($response, 5 + $pos));
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_URL, 'C2DM_SERVER');
}
function disconnect() {
curl_close($this->ch);
$this->authKey = NULL;
}
function sendMessage($deviceToken, $message) {
$data = array(
'registration_id' => $deviceToken,
'collapse_key' => 'ck_type',
'data.type' => 'TYPE',
'data.message' => $message,
'data.title' => 'Title'
);
$headers = array('Authorization: GoogleLogin auth='.$this->authKey);
if($headers)
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($this->ch, CURLOPT_POST, true);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
$messagedata = curl_exec($this->ch);
return TRUE;
}
}
?>
编辑: 新解决方案基于 curl_multi_exec。
在循环通过数据库查询结果时收集卷曲句柄。在收集了几百个 curl 句柄之后,调用 sendMessages($chs) 来发送所有这些消息。目前我在发送前收集了 700 条消息,并且似乎具有良好的传递率和足够快的速度,大约 10 秒可以发送 5000 条消息。较高的数字似乎会影响交付率。
<?php
class C2DMclient
{
private $authKey = NULL;
private $ch = NULL;
function connect() {
$post_params = array(
'Email' => 'C2DM_USER',
'Passwd' => 'C2DM_PWD',
'accountType' => 'HOSTED_OR_GOOGLE',
'source' => 'appname',
'service' => 'ac2dm',
);
$first = true;
$data_msg = '';
foreach($post_params as $key => $value) {
if($first)
$first = false;
else
$data_msg .= '&';
$data_msg .= urlencode($key).'='.urlencode($value);
}
$x = curl_init('C2DM_CLIENTLOGIN');
curl_setopt($x, CURLOPT_HEADER, true);
curl_setopt($x, CURLOPT_POST, true);
curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg);
curl_setopt($x, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($x);
curl_close($x);
$pos = strpos($response, 'Auth=');
$this->authKey = trim(substr($response, 5 + $pos));
}
function getMessageCurlHandle($deviceToken, $message) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'C2DM_SERVER');
$data = array(
'registration_id' => $deviceToken,
'collapse_key' => 'ck_type',
'data.type' => 'TYPE',
'data.message' => $message,
'data.title' => 'Title'
);
$headers = array('Authorization: GoogleLogin auth='.$this->authKey);
if($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
return $ch;
}
function sendMessages($chs) {
$mh = curl_multi_init();
foreach($chs as $ch) {
curl_multi_add_handle($mh, $ch);
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while($mrc == CURLM_CALL_MULTI_PERFORM);
while($active && $mrc == CURLM_OK) {
if(curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
curl_multi_close($mh);
}
}
?>
【问题讨论】:
标签: php android push-notification android-c2dm