你的位置:首页 > ASP.net教程

[ASP.net教程]从苹果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的代码

 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  34       //Set up 35       byte[] buffer = new byte[4096]; 36       int recd = 0; 37       var data = new List<byte>(); 38  39       //Get the first feedback 40       recd = stream.Read(buffer, 0, buffer.Length); 41  42       //Continue while we have results and are not disposing 43       while (recd > 0) 44       { 45         // Add the received data to a list buffer to work with (easier to manipulate) 46         for (int i = 0; i < recd; i++) 47           data.Add(buffer[i]); 48  49         //Process each complete notification "packet" available in the buffer 50         while (data.Count >= (4 + 2 + 32)) // Minimum size for a valid packet 51         { 52           var secondsBuffer = data.GetRange(0, 4).ToArray(); 53           var tokenLengthBuffer = data.GetRange(4, 2).ToArray(); 54  55           // Get our seconds since epoch 56           // Check endianness and reverse if needed 57           if (BitConverter.IsLittleEndian) 58             Array.Reverse(secondsBuffer); 59           var seconds = BitConverter.ToInt32(secondsBuffer, 0); 60  61           //Add seconds since 1970 to that date, in UTC 62           var timestamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(seconds); 63  64           //flag to allow feedback times in UTC or local, but default is local 65           if (!Configuration.FeedbackTimeIsUTC) 66             timestamp = timestamp.ToLocalTime(); 67  68  69           if (BitConverter.IsLittleEndian) 70             Array.Reverse(tokenLengthBuffer); 71           var tokenLength = BitConverter.ToInt16(tokenLengthBuffer, 0); 72  73           if (data.Count >= 4 + 2 + tokenLength) 74           { 75  76             var tokenBuffer = data.GetRange(6, tokenLength).ToArray(); 77             // Strings shouldn't care about endian-ness... this shouldn't be reversed 78             //if (BitConverter.IsLittleEndian) 79             //  Array.Reverse (tokenBuffer); 80             var token = BitConverter.ToString(tokenBuffer).Replace("-", "").ToLower().Trim(); 81  82             // Remove what we parsed from the buffer 83             data.RemoveRange(0, 4 + 2 + tokenLength); 84  85             // Raise the event to the consumer 86             var evt = FeedbackReceived; 87             if (evt != null) 88               evt(token, timestamp); 89           } 90           else 91           { 92             continue; 93           } 94  95         } 96  97         //Read the next feedback 98         recd = stream.Read(buffer, 0, buffer.Length); 99       }100 101       try102       {103         stream.Close();104         stream.Dispose();105       }106       catch { }107 108       try109       {110         client.Client.Shutdown(SocketShutdown.Both);111         client.Client.Dispose();112       }113       catch { }114 115       try { client.Close(); }116       catch { }117     }118   }

View Code

下面是处理逻辑:

 1   /// <summary> 2   /// 处理失效的Token逻辑信息 3   /// </summary> 4   public class TokenProvider 5   { 6     private FeedbackService fs = null; 7     private int hour = 12; 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       try15       {16         int hour = int.Parse(ConfigurationManager.AppSettings["ManagerTokenHour"]);//Token的控制时间17       }18       catch { hour = 12; }19     }20     21     /// <summary>22     /// 开启处理失效的Token逻辑信息23     /// </summary>24     /// <param name="cf"></param>25     public void Init()26     {27       try28       {29         Thread thsub = new Thread(new ThreadStart(() =>30         {31           while (true)32           {33             try34             {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 * 60 * 60 * 1000);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       try60       {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   }

View Code