using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Net;
using System.Timers;
using PushSharp;
using PushSharp.Apple;
namespace ConsoleApplication1
{
//class Program
//{
// static void Main(string[] args)
// {
// X509Certificate2 cert = new X509Certificate2("123.p12", "8dbmds");
// X509CertificateCollection certificate = new X509CertificateCollection();
// certificate.Add(cert);
// //发布模式, 主机地址是 gateway.push.apple.com
// //开发模式, 主机地址是 gateway.sandbox.push.apple.com
// TcpClient client = new TcpClient("gateway.sandbox.push.apple.com", 2195);
// SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ServerCertificateValidationCallback), null);
// //方法AuthenticateAsClient()可能会引起异常,我们需要try..catch..起来
// try
// {
// //SslStream参考
// //https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
// sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", certificate, SslProtocols.Default, false);
// }
// catch (Exception e)
// {
// Console.WriteLine("Exception Message: {0} ", e.Message);
// sslStream.Close();
// }
// //把值赋给payload
// PushNotificationPayload payload = new PushNotificationPayload();
// payload.deviceToken = "b606c95c4b3956de89d67ecfa02811ebc5d1a09c6f832c3be67b1d9554a66683";
// payload.badge = 56789;
// payload.sound = "default";
// payload.message = "This message was pushed by C# platform.";
// Push(payload, sslStream);
// }
// //这是握手后的回调
// private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
// {
// if (sslPolicyErrors == SslPolicyErrors.None)
// {
// Console.WriteLine("Specified Certificate is accepted.");
// return true;
// }
// Console.WriteLine("Certificate error : {0} ", sslPolicyErrors);
// return false;
// }
// //然后调用Push()方法
// public static void Push(PushNotificationPayload payload, SslStream _sslStream)
// {
// string payloadStr = payload.PushPayload();
// string deviceToken = payload.deviceToken;
// MemoryStream memoryStream = new MemoryStream();
// BinaryWriter writer = new BinaryWriter(memoryStream);
// writer.Write((byte)0); //The command
// writer.Write((byte)0); //deviceId长度的第一个字节,大头字节序第一个字节
// writer.Write((byte)32); //deviceId长度,大头字节序第二个字节
// //方法DataWithDeviceToken() , [具体看源码](https://github.com/Victor-Studio/PushNotification)
// byte[] deviceTokenBytes = DataWithDeviceToken(deviceToken.ToUpper());
// writer.Write(deviceTokenBytes);
// writer.Write((byte)0); //payload的长度的第一个字节,大头字节序的第一个字节
// writer.Write((byte)payloadStr.Length); //payload的长度,大头字节序的第二个字节
// byte[] bytes = Encoding.UTF8.GetBytes(payloadStr);
// writer.Write(bytes);
// writer.Flush();
// _sslStream.Write(memoryStream.ToArray());
// _sslStream.Flush();
// Thread.Sleep(3000);
// //方法ReadMessage() , 具体看[本库的源码](https://github.com/Victor-Studio/PushNotification)
// string result = ReadMessage(_sslStream);
// Console.WriteLine("server said: " + result);
// _sslStream.Close();
// }
// static string ReadMessage(SslStream sslStream)
// {
// // Read the message sent by the client.
// // The client signals the end of the message using the
// // "<EOF>" marker.
// byte[] buffer = new byte[2048];
// StringBuilder messageData = new StringBuilder();
// int bytes = -1;
// do
// {
// // Read the client's test message.
// bytes = sslStream.Read(buffer, 0, buffer.Length);
// // Use Decoder class to convert from bytes to UTF8
// // in case a character spans two buffers.
// Decoder decoder = Encoding.UTF8.GetDecoder();
// char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
// decoder.GetChars(buffer, 0, bytes, chars, 0);
// messageData.Append(chars);
// // Check for EOF or an empty message.
// if (messageData.ToString().IndexOf("<EOF>") != -1)
// {
// break;
// }
// }
// while (bytes != 0);
// return messageData.ToString();
// }
//}
class Program
{
public static DateTime? Expiration { get; set; }
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 = "手机标识码";
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)
{
Console.WriteLine("1");
// //发布模式, 主机地址是 gateway.push.apple.com
// //开发模式, 主机地址是 gateway.sandbox.push.apple.com
string hostIP = "gateway.sandbox.push.apple.com";//
int port = 2195;
string password = "证书密码";//
string certificatepath = "证书路径.p12";//bin/debug
string p12Filename = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, certificatepath);
byte[] b = System.IO.File.ReadAllBytes(p12Filename);
certificate = new X509Certificate2(System.IO.File.ReadAllBytes(p12Filename), password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
certificates = new X509CertificateCollection();
certificates.Add(certificate);
Console.WriteLine("2");
TcpClient apnsClient = new TcpClient();
apnsClient.Connect(hostIP, port);
Console.WriteLine("3");
SslStream apnsStream = new SslStream(apnsClient.GetStream(), false, new RemoteCertificateValidationCallback(validateServerCertificate), new LocalCertificateSelectionCallback(selectLocalCertificate));
try
{
Console.WriteLine("4");
//APNs已不支持SSL 3.0
apnsStream.AuthenticateAsClient(hostIP, certificates, System.Security.Authentication.SslProtocols.Tls, false);
Console.WriteLine("5");
}
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!");
}
Console.WriteLine("6");
//Console.WriteLine(ReadMessage(apnsStream));
Console.WriteLine("7");
//Console.WriteLine(ReadMessage(apnsStream));
Byte[] message = ToBytes();
apnsStream.Write(message);
Console.WriteLine("8");
Console.WriteLine(ReadMessage(apnsStream));
Console.ReadLine();
}
static string ReadMessage(SslStream sslStream)
{
// Read the message sent by the client.
// The client signals the end of the message using the
// "<EOF>" marker.
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
// Read the client's test message.
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8
// in case a character spans two buffers.
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);
// Check for EOF or an empty message.
if (messageData.ToString().IndexOf("<EOF>") != -1)
{
break;
}
}
while (bytes != 0);
return messageData.ToString();
}
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\":\"default\"}}";
string str = "{\"aps\" : {\"alert\" : {\"title\" : \"标题\",\"body\" : \"文本\"},\"sound\" : \"default\",\"badge\" : 0}}";
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;
}
}
}
分享到:
相关推荐
苹果APNS推送,C#实现通过APNS向客户手机推送消息,Apple Push Notification Service
总结,C#结合APNS推送技术,可以实现实时、高效地向苹果设备发送通知。在VS2008和SQL2008环境中,我们需要管理Device Tokens,构建推送消息,连接APNS服务器并处理可能出现的错误。通过不断优化和调试,可以构建出...
在IT行业中,苹果推送通知服务(Apple Push Notification Service,简称APNS)是苹果公司提供的一项...通过阅读和理解这些代码,你可以更好地掌握如何在C#和.NET环境中集成APNS,从而实现在苹果设备上的推送通知服务。
C#下实现APNs推送,通常需要一个中间库来处理与服务器的通信。"PushSharp"是一个流行的开源库,用于处理各种平台(包括iOS)的推送通知。在提供的压缩包"PushSharp-master"中,我们可以找到这个库的相关源码和示例。...
总结,C#实现的APNS后台服务为iOS应用提供了便捷的推送通知功能,结合苹果的推送服务,开发者可以实时与用户互动,提升用户体验。在实际开发中,理解APNS的工作机制,选择合适的C#库,以及遵循最佳实践,都是确保推...
4. **推送消息结构**:APNs推送消息包含头信息(如目标设备令牌、通知类型等)和负载数据(如标题、正文、声音等)。C#代码需要构建符合APNs规范的消息结构,并进行序列化。 5. **Windows服务**:Windows服务是一种...
要使用C#进行APNs推送,我们需要以下几个步骤: 1. **获取APNs证书**:在Apple Developer Portal中,开发者需要创建并下载一个用于生产环境或开发环境的推送证书。这个证书包含了安全地与APNs通信所需的私钥。 2. ...
1. **证书管理**:首先,开发者需要在苹果开发者中心创建并下载APNs推送证书,将其转换为.p12格式,然后在C#代码中加载这个证书以建立安全连接。 2. **建立连接**:使用`System.Net.Security.SslStream`类建立SSL/...
在这个源码包中,M2Mqtt可能是用于实现实时消息推送的组件,支持多种平台,包括Visual Studio的不同版本(如2008、2010、2012)以及Mono(一个开源的.NET实现,可用于Linux和其他非Windows系统),这表明这个解决...
总结一下,实现C#中的iPhone APNs推送涉及了证书管理、JSON消息构建、HTTP通信以及多线程处理。通过理解APNs的工作机制,结合C#的网络编程和多线程技术,我们可以构建稳定、高效的推送服务。在实际项目中,还需要...
这是一个基础的APNs推送实现,但实际应用可能需要处理更多细节,如错误重试、批量推送、自定义通知类型等。此外,APNs有两种模式:简单推送(Simple Notification)和增强推送(Enhanced Notification),后者允许...
总结,C#实现手机推送涉及APNS和FCM的使用,借助特定库如APNS-Sharp,可以方便地从后端向iOS和Android设备发送推送通知。在实际开发中,应考虑安全性、性能优化以及错误处理,确保用户能及时收到并正确处理推送信息...
接下来,我们将讨论如何在C#中实现推送功能。C#中可以使用HttpClient类来发起HTTP请求,与极光推送的RESTful API进行交互。以下是一个基本的推送消息示例: ```csharp using System; using System.Collections....
友盟U-Push是由阿里巴巴旗下的友盟提供的推送服务,它允许开发者通过云端平台向用户的设备发送消息,无论是通知、自定义消息或是富媒体消息。其优点在于统一的API接口,跨平台的支持以及丰富的推送策略,如地理位置...
在.NET环境中构建APNS推送服务,我们需要遵循以下步骤: 1. **获取证书和密钥**:在苹果开发者中心创建推送证书,下载.p12文件。这个文件包含了用于身份验证的私钥和证书,是与APNS通信的关键。 2. **集成APNS库**...
标题中的"IOS Android推送 C#"指的是使用C#编程语言实现在iOS和Android平台上进行应用程序的消息推送功能。在移动开发中,推送通知是连接服务器与客户端应用程序的重要桥梁,它能让用户即使在不打开应用的情况下,也...
`.NET推送消息源码`通常涉及使用特定库或框架来实现在不同平台上向用户发送实时通知。`PushSharp`是这样一个开源库,它允许开发者方便地集成多种推送服务,如Google的Firebase Cloud Messaging (FCM)、Apple的Push ...
在CSDN上很多说C#写的给iOS客户端推送信息,都没有什么参考意义,反正我下了几个,都压根不是那么回事。然后自个找了下资料用PushSharp对iOS进行推送。代码很简单,希望能对像我这样的新接触的朋友有帮助。 个人感觉...
4. **连接与发送**:使用C#的HttpClient类或者其他第三方库,如PushSharp,建立安全的TLS连接到APNS服务器,并发送推送消息。注意,必须正确处理连接错误、超时和重试机制。 5. **错误处理**:APNS会返回错误代码,...
标题中的“E4A配合易语言服务器发送推送消息例子源码”揭示了这是一个关于使用E4A(Easy4Android)和易语言开发的服务器端配合实现消息推送的示例项目。这个项目的主要目的是教给开发者如何在Android应用程序中集成...