在开发苹果推送服务时候,要合理的控制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

  1. /// <summary>
  2. /// FeedbackService
  3. /// </summary>
  4. public class FeedbackService
  5. {
  6. public FeedbackService(ApnsConfiguration configuration)
  7. {
  8. Configuration = configuration;
  9. }
  10.  
  11. public ApnsConfiguration Configuration { get; private set; }
  12.  
  13. public delegate void FeedbackReceivedDelegate(string deviceToken, DateTime timestamp);
  14. public event FeedbackReceivedDelegate FeedbackReceived;
  15.  
  16. public void Check()
  17. {
  18. var encoding = Encoding.ASCII;
  19.  
  20. var certificate = Configuration.Certificate;
  21.  
  22. var certificates = new X509CertificateCollection();
  23. certificates.Add(certificate);
  24.  
  25. var client = new TcpClient(Configuration.FeedbackHost, Configuration.FeedbackPort);
  26.  
  27. var stream = new SslStream(client.GetStream(), true,
  28. (sender, cert, chain, sslErrs) => { return true; },
  29. (sender, targetHost, localCerts, remoteCert, acceptableIssuers) => { return certificate; });
  30.  
  31. stream.AuthenticateAsClient(Configuration.FeedbackHost, certificates, System.Security.Authentication.SslProtocols.Tls, false);
  32.  
  33. //Set up
  34. byte[] buffer = new byte[];
  35. int recd = ;
  36. var data = new List<byte>();
  37.  
  38. //Get the first feedback
  39. recd = stream.Read(buffer, , buffer.Length);
  40.  
  41. //Continue while we have results and are not disposing
  42. while (recd > )
  43. {
  44. // Add the received data to a list buffer to work with (easier to manipulate)
  45. for (int i = ; i < recd; i++)
  46. data.Add(buffer[i]);
  47.  
  48. //Process each complete notification "packet" available in the buffer
  49. while (data.Count >= ( + + )) // Minimum size for a valid packet
  50. {
  51. var secondsBuffer = data.GetRange(, ).ToArray();
  52. var tokenLengthBuffer = data.GetRange(, ).ToArray();
  53.  
  54. // Get our seconds since epoch
  55. // Check endianness and reverse if needed
  56. if (BitConverter.IsLittleEndian)
  57. Array.Reverse(secondsBuffer);
  58. var seconds = BitConverter.ToInt32(secondsBuffer, );
  59.  
  60. //Add seconds since 1970 to that date, in UTC
  61. var timestamp = new DateTime(, , , , , , DateTimeKind.Utc).AddSeconds(seconds);
  62.  
  63. //flag to allow feedback times in UTC or local, but default is local
  64. if (!Configuration.FeedbackTimeIsUTC)
  65. timestamp = timestamp.ToLocalTime();
  66.  
  67. if (BitConverter.IsLittleEndian)
  68. Array.Reverse(tokenLengthBuffer);
  69. var tokenLength = BitConverter.ToInt16(tokenLengthBuffer, );
  70.  
  71. if (data.Count >= + + tokenLength)
  72. {
  73.  
  74. var tokenBuffer = data.GetRange(, tokenLength).ToArray();
  75. // Strings shouldn't care about endian-ness... this shouldn't be reversed
  76. //if (BitConverter.IsLittleEndian)
  77. // Array.Reverse (tokenBuffer);
  78. var token = BitConverter.ToString(tokenBuffer).Replace("-", "").ToLower().Trim();
  79.  
  80. // Remove what we parsed from the buffer
  81. data.RemoveRange(, + + tokenLength);
  82.  
  83. // Raise the event to the consumer
  84. var evt = FeedbackReceived;
  85. if (evt != null)
  86. evt(token, timestamp);
  87. }
  88. else
  89. {
  90. continue;
  91. }
  92.  
  93. }
  94.  
  95. //Read the next feedback
  96. recd = stream.Read(buffer, , buffer.Length);
  97. }
  98.  
  99. try
  100. {
  101. stream.Close();
  102. stream.Dispose();
  103. }
  104. catch { }
  105.  
  106. try
  107. {
  108. client.Client.Shutdown(SocketShutdown.Both);
  109. client.Client.Dispose();
  110. }
  111. catch { }
  112.  
  113. try { client.Close(); }
  114. catch { }
  115. }
  116. }

下面是处理逻辑:

  1. /// <summary>
  2. /// 处理失效的Token逻辑信息
  3. /// </summary>
  4. public class TokenProvider
  5. {
  6. private FeedbackService fs = null;
  7. private int hour = ;
  8. private string CID;
  9.  
  10. public TokenProvider(ApnsConfiguration cf, string CID)
  11. {
  12. this.fs = fs = new FeedbackService(cf);
  13. this.CID = CID;
  14. try
  15. {
  16. int hour = int.Parse(ConfigurationManager.AppSettings["ManagerTokenHour"]);//Token的控制时间
  17. }
  18. catch { hour = ; }
  19. }
  20.  
  21. /// <summary>
  22. /// 开启处理失效的Token逻辑信息
  23. /// </summary>
  24. /// <param name="cf"></param>
  25. public void Init()
  26. {
  27. try
  28. {
  29. Thread thsub = new Thread(new ThreadStart(() =>
  30. {
  31. while (true)
  32. {
  33. try
  34. {
  35. fs.Check();
  36. }
  37. catch (Exception ex)
  38. {
  39. LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = " fs.Check() Error! CID=" + CID, ExInfo = ex });
  40. }
  41. Thread.Sleep(hour * * * );
  42. }
  43. }));
  44. fs.FeedbackReceived += fs_FeedbackReceived;
  45. thsub.Start();
  46. LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Open TokenProvider! CID=" + CID });
  47. }
  48. catch (Exception ex)
  49. { LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = " Open TokenProvider Error! CID=" + CID, ExInfo = ex }); }
  50. }
  51.  
  52. /// <summary>
  53. /// 处理失效的Token信息
  54. /// </summary>
  55. /// <param name="deviceToken"></param>
  56. /// <param name="timestamp"></param>
  57. private void fs_FeedbackReceived(string deviceToken, DateTime timestamp)
  58. {
  59. try
  60. {
  61. p_DeleteToken p = new p_DeleteToken(deviceToken);
  62. if (p.ExecutionDelete()) {
  63. LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Delete lose token success >> " + deviceToken });
  64. } else {
  65. LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "Delete lose token error >> " + deviceToken, ExInfo = null });
  66. };
  67. }
  68. catch (Exception ex)
  69. {
  70. LogInfoProvider.config.Logs.Add(new LogClass() { LogStr = "fs_FeedbackReceived Error! CID=" + CID, ExInfo = ex });
  71. }
  72. }
  73. }

APNS IOS 消息推送处理失效的Token的更多相关文章

  1. APNS IOS 消息推送

    一.Apns简介: Apns是苹果推送通知服务. 二.原理: APNs会对用户进行物理连接认证,和设备令牌认证(简言之就是苹果的服务器检查设备里的证书以确定其为苹果设备):然后,将服务器的信息接收并且 ...

  2. APNS IOS 消息推送沙盒模式和发布模式

    在做.NET向IOS设备的App进行消息推送时候,采用的是PushSharp开源类库进行消息的推送,而在开发过程中,采用的是测试版本的app,使用的是测试的p12证书采用的是ApnsConfigura ...

  3. APNS IOS 消息推送JSON格式介绍

    在开发向苹果Apns推送消息服务功能,我们需要根据Apns接受的数据格式进行推送.下面积累了我在进行apns推送时候总结的 apns服务接受的Json数据格式 示例 1: 以下负载包含哦一个简单的 a ...

  4. iOS 消息推送(APNs) 傻瓜式教程

    也可以去我的简书页面查看这篇文章 首先: 1.做iOS消息推送需要真机测试 2.做iOS消息推送需要有付费的开发者账号 是否继续看帖? 先学习一下相关的知识吧! 因为中途可能会遇到一些问题,这篇文章或 ...

  5. Ios 消息推送

    手把手教你做iOS推送 http://www.cocoachina.com/industry/20130321/5862.html http://www.cnblogs.com/cdts_change ...

  6. .NET向APNS苹果消息推送通知

    一.Apns简介: Apns是苹果推送通知服务. 二.原理: APNs会对用户进行物理连接认证,和设备令牌认证(简言之就是苹果的服务器检查设备里的证书以确定其为苹果设备):然后,将服务器的信息接收并且 ...

  7. ios 消息推送流程 转载

    iOS开发:推送通知简述及开发实践热度 1已有 706 次阅读 2013-10-15 09:23 |个人分类:经验之谈|系统分类:ios| IOS, 推送一.关于推送通知 推送通知,也被叫做远程通知, ...

  8. (转)iOS消息推送机制的实现

    原:http://www.cnblogs.com/qq78292959/archive/2012/07/16/2593651.html iOS消息推送机制的实现 iOS消息推送的工作机制可以简单的用下 ...

  9. 【iOS】iOS消息推送机制的实现

    iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务 ...

随机推荐

  1. 用yii2给app写接口(下)

    上一节里我们讲了如何用Yii2搭建一个能够给App提供数据的API后台应用程序.那么今天我们就来探讨下授权认证和通过API接口向服务器提交数据以及如何控制API接口返回那些数据,不能返回那些数据. 授 ...

  2. Opencv 330 如何進行圖像的旋轉?

    //圖像旋轉 cv::Mat Transformation(cv::Mat src,int angle) { cv::Mat dst = src.clone(); //中心点 cv::Point ce ...

  3. javascript正则表达式的一些笔记

    正则表达式:Regular Expression.使用单个字符串来描述,匹配一系列符合某个句法规则的字符串.即按照某种规则去匹配符合条件的字符串.正则表达式就是规则. \b 单词边界 regexp对象 ...

  4. python模拟登录浙江大学彩云库

    前言: 群里一位朋友叫我帮他写 一个模拟登录的. 代码: import requests import time url="http://yk3.gokuai.com/web/index&q ...

  5. git 命令和使用场景总结

    资料地址:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000    http://w ...

  6. Git 用户名和邮箱

    用户名邮箱的作用 用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变. 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. 查看用 ...

  7. iOS 开发之内存泄漏问题

    关于内存泄漏问题,一般情况下就是控制器或者视图没有正常的释放引起的,我们通常可以通过dealloc方法来检查一个控制器或者视图是否释放. 对于一个控制器或者视图没有释放,其实也就是还有强引用引用着这个 ...

  8. mysql数据库基本使用(增删改查)

    数据库db,database 数据库:依照某种数据模型进行组织并存放到存储器的数据集合dbms,database management system 数据库管理系统:用来操作和管理数据库的大型服务软件 ...

  9. 吐槽版︱MRO-Microsoft R Open快捷键+界面识别+功能设置

    下载了之后,发现连运行(RUN键)在哪都不知道,蒙逼的在哪倒弄半天,都执行不了...问了别人,都说"ctrl+enter",但是我的电脑执行不了,于是今天就狠狠的一个一个按钮的点一 ...

  10. [javascript]一段焦点图的js代码

    <html> <head> <meta name="name" content="content"charset="ut ...