如何用 php代码实现 ios 等多台设备的推送信息功能?
可能有6-10万的终端设备都需要接收到推送信息,执行一次,实现多台设备都能接收到信息。
路过的给点有用的建议,谢谢啦!!!
回复讨论(解决方案)
这个用php不好实现吧。
肯定不建议用长连接一直连着,直到有有消息就返回给用户,这样的话服务器压力肯定很大。
建议可以用心跳来实现这个功能,客户端浏览器定时向服务器获取是否有最新消息。
另外,如果不是php,比如python、nodejs、c++等实现后台,可以采用长轮询。
这个用php不好实现吧。
肯定不建议用长连接一直连着,直到有有消息就返回给用户,这样的话服务器压力肯定很大。
建议可以用心跳来实现这个功能,客户端浏览器定时向服务器获取是否有最新消息。
另外,如果不是php,比如python、nodejs、c++等实现后台,可以采用长轮询。
6-10万用一台机器长连接也不大可能,呵呵
这不是 php 能做到的!
php 是服务器端脚本,而不是服务器,更不是网络操作系统
你只不过是需要套用一下移动通讯的操作系统就能实现你的目标
你要源代码自己去移动版->iphone,正好有个坛友发了个你需要得帖子
我也可以跟你说说我怎么做的,其实很简单,主要是用苹果开发账号生成证书那里要搞搞。
步骤1
-------
首先你得用php在服务端开个接口,提供给iphone手机注册device_token,也就是装了你应用的手机会向这个接口做一个http请求,把每台机器的device_token以及一些参数提交过来,然后你用php接收,存到数据库
步骤2
-----------
用php读数据,把注册的device_token从数据库读出来,拼接成一串规定格式的串,带上生成的苹果证书,往苹果提供的推送服务api做一个socket请求
关键代码1:
stream_context_set_option($ctx, 'ssl', 'local_cert', $pemFile);//$pemFile为证书文件,这个你自己上网找找生成步骤,你必须得有个apple开发帐号$ctx = stream_context_create();stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); // Open a connection to the APNS server,推送服务api,以下是沙箱环境$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
关健代码2:
// Create the payload body $body['aps'] = array( 'alert' => array( 'body' => $message, //'action-loc-key' => 'Bango App', ), 'badge' => $badge, 'sound' => 'oven.caf', ); $deviceTokens = array(); $payload = FMFactory::GetJson()->encode($body); $regs = FMFactory::GetQuery()->from("mobile_pn_register as m","m.*") ->where("m.mobiletype='ios' and m.registered_app_id='{$app_record_id}'") ->query(); if(!count($regs)) { throw new Exception(MOBILE_NOT_REGISTER_PUSH_NOTIFICATION_YET); } //根据协议生成请求串 foreach((array)$regs as $reg) { $msg = chr(0) . pack('n', 32) . pack('H*', $reg['devicetoken']) . pack('n', strlen($payload)) . $payload; // Send it to the server $result = fwrite($fp, $msg, strlen($msg)); }
关键代码1那里copy出错了,应如以下
$passphrase = '';$ctx = stream_context_create();stream_context_set_option($ctx, 'ssl', 'local_cert', $pemFile);stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);// Open a connection to the APNS server,推送服务api,以下是沙箱环境$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
php发送邮件?推送?
你要源代码自己去移动版->iphone,正好有个坛友发了个你需要得帖子
我也可以跟你说说我怎么做的,其实很简单,主要是用苹果开发账号生成证书那里要搞搞。
步骤1
-------
首先你得用php在服务端开个接口,提供给iphone手机注册device_token,也就是装了你应用的手机会向这个接口做一个http请求,把每台机器的device_token以及一些参数提交过来,然后你用php接收,存到数据库
步骤2
-----------
用php读数据,把注册的device_token从数据库读出来,拼接成一串规定格式的串,带上生成的苹果证书,往苹果提供的推送服务api做一个socket请求
关键代码1:
stream_context_set_option($ctx, 'ssl', 'local_cert', $pemFile);//$pemFile为证书文件,这个你自己上网找找生成步骤,你必须得有个apple开发帐号$ctx = stream_context_create();stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); // Open a connection to the APNS server,推送服务api,以下是沙箱环境$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
关健代码2:
// Create the payload body $body['aps'] = array( 'alert' => array( 'body' => $message, //'action-loc-key' => 'Bango App', ), 'badge' => $badge, 'sound' => 'oven.caf', ); $deviceTokens = array(); $payload = FMFactory::GetJson()->encode($body); $regs = FMFactory::GetQuery()->from("mobile_pn_register as m","m.*") ->where("m.mobiletype='ios' and m.registered_app_id='{$app_record_id}'") ->query(); if(!count($regs)) { throw new Exception(MOBILE_NOT_REGISTER_PUSH_NOTIFICATION_YET); } //根据协议生成请求串 foreach((array)$regs as $reg) { $msg = chr(0) . pack('n', 32) . pack('H*', $reg['devicetoken']) . pack('n', strlen($payload)) . $payload; // Send it to the server $result = fwrite($fp, $msg, strlen($msg)); }把所有设备号取出来放入一个数组里,如果是6-10万的话,这个数组会不会太大?
有没有更好的方案,能把这个大数组,拆分成若干个小数组?这样小数组的效率,和整个大数组的效率哪个更好一些呢?
php发送邮件?推送?
是IOS推送那你可以开几个php进程发送嘛,一个发送1w条。
那你可以开几个php进程发送嘛,一个发送1w条。
怎么开进程?怎么写?
那你可以开几个php进程发送嘛,一个发送1w条。
可以利用cronjob
php -f send_apns.php 1 10000 #往数据库里1至10000的device_token推送消息
php -f send_apns.php 10000 20000
php -f send_apns.php 20000 30000
但是仔细想想,我觉得你还是先别切分进程了,你还是先把功能实现了再说,碰到问题再解决问题
这种情况效率不效率主要在于你和服务器的连接方式,因为是socket直连,非http(当然http也有keepalive),所以你切分进程反而可能还慢,每个进程需要重新建立socket连接。
所以,just do it,骚年。
那你可以开几个php进程发送嘛,一个发送1w条。
这个切分进程具体怎么用啊?怎么加到你前面的代码里?
如果是linux下跑的php可以用pcntl_fork跑几个子进程运行下看看。
cronjob也可以,不过需要数据库做些设计,意思是每隔一段时间,检查有无要发送的信息,和群发邮件一个道理
不过我觉得20000条45分钟还行吧,10万条怎么会用到1天。。也得看你们服务器连接apple api的速度如何啊。
丢包问题是个大问题,我这边还没远远到往20000台发送这种规模,也没遇到过
这里有个问题
http://*.com/questions/12708486/send-push-notification-to-multiple-devices-apns-response-is-negative-after-a-wh
也是丢包问题,貌似是苹果那边认为你的socket连接不活跃,会关闭连接,所以这边的代码是不是有个重连的机制,这个要靠你自己去想了。
如果是linux下跑的php可以用pcntl_fork跑几个子进程运行下看看。
cronjob也可以,不过需要数据库做些设计,意思是每隔一段时间,检查有无要发送的信息,和群发邮件一个道理
不过我觉得20000条45分钟还行吧,10万条怎么会用到1天。。也得看你们服务器连接apple api的速度如何啊。
丢包问题是个大问题,我这边还没远远到往20000台发送这种规模,也没遇到过
这里有个问题
http://*.com/questions/12708486/send-push-notification-to-multiple-devices-apns-response-is-negative-after-a-wh
也是丢包问题,貌似是苹果那边认为你的socket连接不活跃,会关闭连接,所以这边的代码是不是有个重连的机制,这个要靠你自己去想了。
foreach((array)$regs as $reg) { $msg = chr(0) . pack('n', 32) . pack('H*', $reg['devicetoken']) . pack('n', strlen($payload)) . $payload; // Send it to the server $result = fwrite($fp, $msg, strlen($msg)); }我这么写的时候,丢包现象很严重!发几万设备只能发送成功几百个。把$fp放在循环里,丢包还是有,相对少一些。两万设备能有十几个设备不成功!
请问你是发多少个设备呢?
可以试下这样
while(true){ $j = count($regs); for($i=0;$i汗,编辑不了帖子真是麻烦。
while(true){ $j = count($regs); for($i=0;$i
汗,编辑不了帖子真是麻烦。
while(true){ $j = count($regs); for($i=0;$iif(!$result) {//发送失败,socket 重连 $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); }要是这么写的话,是否成功的消息写在哪?ApnsPHP-master
搜下这个吧,我用这个写过,一次推1万,crontab定时发送的,好像没遇到什么情况我传到linux服务器上测试了,貌似$ctx = stream_context_create();不好用啊。怎么回事?
汗,编辑不了帖子真是麻烦。while(true){ $j = count($regs); for($i=0;$iif(!$result) {//发送失败,socket 重连 $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); }要是这么写的话,是否成功的消息写在哪?
我传到linux服务器上测试了,貌似$ctx = stream_context_create();不好用啊。怎么回事?$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx);if (!$fp) {fwrite($fps,"Failed to connect: $err $errstr");}运行结果是:Failed to connect:0
ApnsPHP-master
搜下这个吧,我用这个写过,一次推1万,crontab定时发送的,好像没遇到什么情况
一次推1万 是怎么推的?我这边推100条都很慢,有什么好方法吗?