zoukankan      html  css  js  c++  java
  • C# 推送信息到APNs

    iPhone消息推送机制实现与探讨


    class Program
        {
     
            public static DateTime? Expiration { getset; }
     
            public static readonly DateTime DoNotStore = DateTime.MinValue;
            private static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            private static string DeviceToken = "273eeddaef02192cf4ba5b666453b258f2d2a1ad02f549105fd03fea789d809d";
            public const int DEVICE_TOKEN_BINARY_SIZE = 32;
            public const int DEVICE_TOKEN_STRING_SIZE = 64;
            public const int MAX_PAYLOAD_SIZE = 256;
            private static X509Certificate certificate;
            private static X509CertificateCollection certificates;
     
            static void Main(string[] args)
            {
                string hostIP = "gateway.sandbox.push.apple.com";//
                int port = 2195;
                string password = "ankejiaoyu";//
                string certificatepath = "aps_developer_identity.p12";//bin/debug
                string p12Filename = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, certificatepath);
     
     
                certificate = new X509Certificate2(System.IO.File.ReadAllBytes(p12Filename), password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
     
                certificates = new X509CertificateCollection();
                certificates.Add(certificate);
     
     
                TcpClient apnsClient = new TcpClient();
                apnsClient.Connect(hostIP, port);
     
                SslStream apnsStream = new SslStream(apnsClient.GetStream(), falsenew RemoteCertificateValidationCallback(validateServerCertificate), new LocalCertificateSelectionCallback(selectLocalCertificate));
     
                try
                {
                    //APNs已不支持SSL 3.0 
                    apnsStream.AuthenticateAsClient(hostIP, certificates, System.Security.Authentication.SslProtocols.Tls, false);
                }
                catch (System.Security.Authentication.AuthenticationException ex)
                {
                    Console.WriteLine("error+"+ex.Message);
                }
     
                if (!apnsStream.IsMutuallyAuthenticated)
                {
                    Console.WriteLine("error:Ssl Stream Failed to Authenticate!");
                }
     
                if (!apnsStream.CanWrite)
                {
                    Console.WriteLine("error:Ssl Stream is not Writable!");
                    
                }
     
                Byte[] message = ToBytes();
                apnsStream.Write(message);
            }
     
            public static byte[] ToBytes()
            {
     
                // Without reading the response which would make any identifier useful, it seems silly to
                // expose the value in the object model, although that would be easy enough to do. For
                // now we'll just use zero.
                int identifier = 0;
                byte[] identifierBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(identifier));
     
                // APNS will not store-and-forward a notification with no expiry, so set it one year in the future
                // if the client does not provide it.
                int expiryTimeStamp = -1;//过期时间戳
                if (Expiration != DoNotStore)
                {
                    //DateTime concreteExpireDateUtc = (Expiration ?? DateTime.UtcNow.AddMonths(1)).ToUniversalTime();
                    DateTime concreteExpireDateUtc = (Expiration ?? DateTime.UtcNow.AddSeconds(20)).ToUniversalTime();
                    TimeSpan epochTimeSpan = concreteExpireDateUtc - UNIX_EPOCH;
                    expiryTimeStamp = (int)epochTimeSpan.TotalSeconds;
                }
     
                byte[] expiry = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(expiryTimeStamp));
     
                byte[] deviceToken = new byte[DeviceToken.Length / 2];
                for (int i = 0; i < deviceToken.Length; i++)
                    deviceToken[i] = byte.Parse(DeviceToken.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
     
                if (deviceToken.Length != DEVICE_TOKEN_BINARY_SIZE)
                {
                    Console.WriteLine("Device token length error!");
                }
     
                byte[] deviceTokenSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Convert.ToInt16(deviceToken.Length)));
                string str = "{"aps":{"alert":"这是测试消息!!","badge":1,"sound":"anke.mp3"}}";
     
                byte[] payload = Encoding.UTF8.GetBytes(str);
     
                byte[] payloadSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Convert.ToInt16(payload.Length)));
                List<byte[]> notificationParts = new List<byte[]>();
                //1 Command
                notificationParts.Add(new byte[] { 0x01 }); // Enhanced notification format command
                notificationParts.Add(identifierBytes);
                notificationParts.Add(expiry);
                notificationParts.Add(deviceTokenSize);
                notificationParts.Add(deviceToken);
                notificationParts.Add(payloadSize);
                notificationParts.Add(payload);
     
                return BuildBufferFrom(notificationParts);
            }
     
            private static byte[] BuildBufferFrom(IList<byte[]> bufferParts)
            {
                int bufferSize = 0;
                for (int i = 0; i < bufferParts.Count; i++)
                    bufferSize += bufferParts[i].Length;
     
                byte[] buffer = new byte[bufferSize];
                int position = 0;
                for (int i = 0; i < bufferParts.Count; i++)
                {
                    byte[] part = bufferParts[i];
                    Buffer.BlockCopy(bufferParts[i], 0, buffer, position, part.Length);
                    position += part.Length;
                }
                return buffer;
            }
     
            private static bool validateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return true// Dont care about server's cert
            }
     
            private static X509Certificate selectLocalCertificate(object sender, string targetHost, X509CertificateCollection localCertificates,
                X509Certificate remoteCertificate, string[] acceptableIssuers)
            {
                return certificate;
            }

        }

    PS:上面这段代码是从网上找的,做了些小改动。



  • 相关阅读:
    C++隐式推导-auto关键词
    git的几种实用操作(合并代码与暂存复原代码)
    CPU的后记,程序员的未来之计
    CPU中的程序是怎么运行起来的
    nginx-日志切割
    Linux里面使用navicat连接MySQL数据显示2002-Can't connect to local MysQL serverthrough socket'/var/lib/mysq/mysql.sock'(13"权限不够")
    Cacti图形中的方框乱码解决办法
    Cacti1.2.14最新版安装和配置(详细版)
    ERROR 1419 (HY000) at line 9: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
    Linux服务器查看对应网卡的网口
  • 原文地址:https://www.cnblogs.com/czblogs/p/4478195.html
Copyright © 2011-2022 走看看