zoukankan      html  css  js  c++  java
  • APNS IOS 消息推送处理失效的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

        /// <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
                byte[] buffer = new byte[4096];
                int recd = 0;
                var data = new List<byte>();
    
                //Get the first feedback
                recd = stream.Read(buffer, 0, buffer.Length);
    
                //Continue while we have results and are not disposing
                while (recd > 0)
                {
                    // Add the received data to a list buffer to work with (easier to manipulate)
                    for (int i = 0; i < recd; i++)
                        data.Add(buffer[i]);
    
                    //Process each complete notification "packet" available in the buffer
                    while (data.Count >= (4 + 2 + 32)) // Minimum size for a valid packet
                    {
                        var secondsBuffer = data.GetRange(0, 4).ToArray();
                        var tokenLengthBuffer = data.GetRange(4, 2).ToArray();
    
                        // Get our seconds since epoch
                        // Check endianness and reverse if needed
                        if (BitConverter.IsLittleEndian)
                            Array.Reverse(secondsBuffer);
                        var seconds = BitConverter.ToInt32(secondsBuffer, 0);
    
                        //Add seconds since 1970 to that date, in UTC
                        var timestamp = new DateTime(1970, 1, 1, 0, 0, 0, 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);
                        var tokenLength = BitConverter.ToInt16(tokenLengthBuffer, 0);
    
                        if (data.Count >= 4 + 2 + tokenLength)
                        {
    
                            var tokenBuffer = data.GetRange(6, 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(0, 4 + 2 + 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, 0, 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 int hour = 12;
            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的控制时间
                }
                catch { hour = 12; }
            }
            
            /// <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 * 60 * 60 * 1000);
                        }
                    }));
                    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 });
                }
            }
        }
  • 相关阅读:
    Python变量、标识符
    PyCharm中设置作者信息
    去中心化
    复杂逻辑---取数
    行政机构处理
    2020.11案例分析
    中间表
    软考--项目管理名词
    软考--近6次上午考点分析
    软考--学习方法、做题方法
  • 原文地址:https://www.cnblogs.com/heyangyi/p/8538729.html
Copyright © 2011-2022 走看看