从苹果apns的feedback服务器获取推送失败的token
在开发自己的苹果推送服务时候,要合理的控制ios设备的Token,而这个Token是由苹果服务器Apns产生的,就是每次app问Apns要Token,由苹果服务器产生的Token会记录到Apns里面,我们需要根据该Token进行制定设备的消息推送,所有Token需要我们自己去记录和管理,每个设备对应唯一的Token,而app的用户登录会有自己约束的别名,与该tokne进行关系绑定,这样按该别名进行推送,就可以找到对应的Token,进而推送到该iso设备上,对应失效的Token我们需要访问苹果的feedbackServer,拿取失效的Token,然后把本地记录的失效token进行移除。
注意事项:
1.建议和feedback服务器建立长连接,连接过于频繁有可能被当做攻击(简简单单的做一些测试时没有关系的);所有在实际开发完成后,我们基本上可以半天与feedback服务器建立一次socket连接,拿取失效的token,
2.获取的token是在上次你给你的应用发推送失败时加feedback服务的,里面会返回失败的具体时间.
3.返回的数据由三部分组成,请看下面的图:
构中包含三个部分,第一部分是一个上次发推送失败的时间戳,第二个部分是device_token的长度,第三部分就是失效的device_token
贴下PushSharp中连接feedback的代码
/// <summary> /// FeedbackService /// </summary> public class FeedbackService { public FeedbackService(ApnsConfiguration configuration) { Configuration = configuration; } public ApnsConfiguration Configuration { get; private set; } public delegate void FeedbackReceivedDelegate(string deviceToken, DateTime timestamp); public event FeedbackReceivedDelegate FeedbackReceived; public void Check() { var encoding = Encoding.ASCII; var certificate = Configuration.Certificate; var certificates = new X509CertificateCollection(); certificates.Add(certificate); var client = new TcpClient(Configuration.FeedbackHost, Configuration.FeedbackPort); var stream = new SslStream(client.GetStream(), true, (sender, cert, chain, sslErrs) => { return true; }, (sender, targetHost, localCerts, remoteCert, acceptableIssuers) => { return certificate; }); stream.AuthenticateAsClient(Configuration.FeedbackHost, certificates, System.Security.Authentication.SslProtocols.Tls, false); //Set up ]; ; var data = new List<byte>(); //Get the first feedback recd = stream.Read(buffer, , buffer.Length); //Continue while we have results and are not disposing ) { // Add the received data to a list buffer to work with (easier to manipulate) ; i < recd; i++) data.Add(buffer[i]); //Process each complete notification "packet" available in the buffer + + )) // Minimum size for a valid packet { , ).ToArray(); , ).ToArray(); // Get our seconds since epoch // Check endianness and reverse if needed if (BitConverter.IsLittleEndian) Array.Reverse(secondsBuffer); ); //Add seconds since 1970 to that date, in UTC , , , , , , DateTimeKind.Utc).AddSeconds(seconds); //flag to allow feedback times in UTC or local, but default is local if (!Configuration.FeedbackTimeIsUTC) timestamp = timestamp.ToLocalTime(); if (BitConverter.IsLittleEndian) Array.Reverse(tokenLengthBuffer); ); + + tokenLength) { , tokenLength).ToArray(); // Strings shouldn't care about endian-ness... this shouldn't be reversed //if (BitConverter.IsLittleEndian) // Array.Reverse (tokenBuffer); var token = BitConverter.ToString(tokenBuffer).Replace("-", "").ToLower().Trim(); // Remove what we parsed from the buffer data.RemoveRange(, + + tokenLength); // Raise the event to the consumer var evt = FeedbackReceived; if (evt != null) evt(token, timestamp); } else { continue; } } //Read the next feedback recd = stream.Read(buffer, , buffer.Length); } try { stream.Close(); stream.Dispose(); } catch { } try { client.Client.Shutdown(SocketShutdown.Both); client.Client.Dispose(); } catch { } try { client.Close(); } catch { } } }
下面是处理逻辑:
/// <summary> /// 处理失效的Token逻辑信息 /// </summary> public class TokenProvider { private FeedbackService fs = null; ; private string CID; public TokenProvider(ApnsConfiguration cf, string CID) { this.fs = fs = new FeedbackService(cf); this.CID = CID; try { int hour = int.Parse(ConfigurationManager.AppSettings["ManagerTokenHour"]);//Token的控制时间 } ; } } /// <summary> /// 开启处理失效的Token逻辑信息 /// </summary> /// <param name="cf"></param> public void Init() { try { Thread thsub = new Thread(new ThreadStart(() => { while (true) { try { fs.Check(); } catch (Exception ex) { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = " fs.Check() Error! CID=" + CID, ExInfo = ex }); } Thread.Sleep(hour * * * ); } })); fs.FeedbackReceived += fs_FeedbackReceived; thsub.Start(); LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Open TokenProvider! CID=" + CID }); } catch (Exception ex) { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = " Open TokenProvider Error! CID=" + CID, ExInfo = ex }); } } /// <summary> /// 处理失效的Token信息 /// </summary> /// <param name="deviceToken"></param> /// <param name="timestamp"></param> private void fs_FeedbackReceived(string deviceToken, DateTime timestamp) { try { p_DeleteToken p = new p_DeleteToken(deviceToken); if (p.ExecutionDelete()) { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Delete lose token success >> " + deviceToken }); } else { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Delete lose token error >> " + deviceToken, ExInfo = null }); }; } catch (Exception ex) { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "fs_FeedbackReceived Error! CID=" + CID, ExInfo = ex }); } } }
从苹果apns的feedback服务器获取推送失败的token的更多相关文章
- javascript跨域传递消息 / 服务器实时推送总结
参考文档,下面有转载[非常好的两篇文章]: http://www.cnblogs.com/loveis715/p/4592246.html [跨源的各种方法总结] http://kb.cnblogs. ...
- iOS,APP退到后台,获取推送成功的内容并且语音播报内容。
老铁,我今天忙了一下午就为解决这个问题,网上有一些方法,说了一堆关于这个挂到后台收到推送并且获得推送内容的问题,有很多人都说APP挂到后台一会就被杀死.但实际上可以有办法解决的. WechatIMG3 ...
- php 微信客服信息推送失败 微信重复推送客服消息 40001 45047
/*** * 微信客服发送信息 * 微信客服信息推送失败 微信重复推送客服消息 40001 45047 * 递归提交到微信 直到提交成功 * @param $openid * @param int $ ...
- SignalR SelfHost实时消息,集成到web中,实现服务器消息推送
先前用过两次SignalR,但是中途有段时间没弄了,今天重新弄,发现已经忘得差不多了,做个笔记! 首先创建一个控制台项目Nuget添加引用联机搜索:Microsoft.AspNet.SignalR.S ...
- IOS 在不打开电话服务的时候,可以响应服务器的推送消息,从而接收服务器的推送消息
在做即时通讯(基于xmpp框架)的时候遇到这样一个问题,就是在真机测试的时候,你按Home键返回桌面,在你返回桌面的时候,这是你的程序的挂起状态的,在你挂起的时候, 相当于你的程序是死的,程序的所有进 ...
- 利用nginx_push_stream_module实现服务器消息推送
NGiNX_HTTP_Push_Module 是一个 Nginx 的扩展模块,它实现了 HTTP Push 和Comet server的功能.HTTP Push 被经常用在网页上主动推的技术,例如一些 ...
- [Apple开发者帐户帮助]六、配置应用服务(5.3)推送通知(APN):从您的Web服务器发送推送通知
要使用APN从Web服务器向macOS用户发送推送通知,请注册网站推送标识符并创建网站推送证书. 对于每个网站,请注册一个网站推送标识符,用于验证通知是否来自您的服务器.然后创建一个网站推送证书以签署 ...
- html5:服务器事件推送(server-sent events)Asp.net
支持 不支持IE 个人理解说明 个人理解:这种消息推送方式不太推广,原因有以下三点~~~`我怎么老是学这些自己认为不会推广的东西呢~汗 在.net中,framework4.5以上就可以由SignalR ...
- HTML5服务器消息推送(java版)
前端代码(html5.html): <html> <meta http-equiv="Content-Type" content="text/html; ...
随机推荐
- Spark源码系列(二)RDD详解
1.什么是RDD? 上一章讲了Spark提交作业的过程,这一章我们要讲RDD.简单的讲,RDD就是Spark的input,知道input是啥吧,就是输入的数据. RDD的全名是Resilient Di ...
- 程序员之路:以Android证道
大道三千,何以证道? 最近有私信.邮件给我咨询一些职业生涯规划的同学,我在这里以过来人的身份给大家一些建议. 任何行业,任何职位,无论高低,无论大小,都可以分为广博.精深两个方向. 精深自然指的是在某 ...
- hao.360.cn不停跳....
最近单位里访问hao.360.cn经常会跳....无限循环,有时跳几十次后才会打开.... 但是,单位里走电信出口部分的电脑就没有问题...同样的电脑(移动出口)的用360浏览器.火狐也问题不大,关键 ...
- ux.form.field.TreePicker 扩展,修复火狐不能展开bug
/** * A Picker field that contains a tree panel on its popup, enabling selection of tree nodes. * 动态 ...
- centos下配置java环境变量
一. 需要配置的环境变量1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下的bin ...
- rsync安装配置及故障解决完全教程[window, 文件同步]
Rsync是的全称是: remote synchronize, 也就是远程同步数据, 它是一款不错的文件同步软件,而且是免费的, 它在镜像保存整个目录树和文件系统的同时保持原来文件的权限.时间.软硬链 ...
- 编写高质量JS代码的68个有效方法(十一)
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- DDD:Repository和UnitOfWork的生命周期问题
UnitOfWork UnitOfWork是一种有状态的.用例级别的对象.如果不采用ORM是不会使用UnitOfWork模式的, Repository Repository是一种特殊的领域服务,因此是 ...
- 【转载】解决 Subversion 的 “svn: Can't convert string from 'UTF-8' to native encoding” 错误
转载自:http://blog.csdn.net/shaohui/article/details/3996274 在google code 上创建了一个新的项目, 用Windows 下面的tortoi ...
- [linux]收集一些好玩的命令
1.rev命令 反转输出,输入的字符串. 在终端中输入:rev 输入需要字符串(支持中文) 2.asciiview命令 安装aview:apt-get install aview 再安装imagema ...