首页 > 编程语言 >APNs(Apple Push Notification server)服务器代码C#编写

APNs(Apple Push Notification server)服务器代码C#编写

时间:2023-05-21 23:03:44浏览次数:55  
标签:Apple C# Notification writer System APNs 通知 payload 字节


PushNotification

使用最简单的方式通过APNs发送通知, 本库使用C#写的服务器端代码,C/Objective-C客户端代码

原地址
Github地址

APNs 概述

Apple推送通知服务,是一个稳健性和高效率性的远程通知,具有中心化的特性。APNs可以传送通知消息到iOS,WatchOS, tvOS 和macOS的设备。 在应用初始化启动时,会创建一个受信任的和加密的IP链接到APNs服务器。APNs发送通知是使用一个持久连接的方式。如果一个通知到达了用户的设备,但是应用没有启动,那么设备暂存通知,直到在合适的时间里相应的应用去处理它。

另外,APNs和你的应用需要用通知来交互,所以你必须配置你自己的服务器(公司的服务器)作为原始发送的通知的服务器,叫做provider, 这个provider需要做到如下几条
* 接收设备的device token和发送相关的通知到APNs,APNs会把相应的通知发送给具体的设备的具体应用
* 何时发送远程通知到用户设备上
* 构建JSON字典,该字典就是通知的payload, 用来描述通知的具体显示
* 发送正确的payload和device token到APNs服务器
* 通过持久的和安全的通道发送请求到APNs,使用HTTP/2网络协议

APNs(Apple Push Notification server)服务器代码C#编写_APNs

这个库可以做什么?

  • 提供最简单的方式发送远程通知到用户的设备,并且是C#写的
  • 使用最简单的C#/Objective-C代码去编写,即时是新手也能很容易理解
  • 如果你是一名iOS开发者,那么这个库很方便与你的iOS测试
  • 如果你是一名ASP.NET/C#开发者,那么这个库很方便的让你编写APNs服务器端代码

更多详情,请看 这里.

简介

服务器端代码(C#)
- 以下是一个最简单的payload远程通知

{"aps":{"alert":"This is a message for testing APNs","badge":123,"sound":"default"}}

这些头文件需要被引用

using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
  • 读取p12文件,从Apple Developer Website下载的,变量certFilePath是p12证书的完整路径,变量certPwd是证书密码,以下是调用代码:
X509Certificate2 cert = new X509Certificate2(certFilePath, certPwd);
X509CertificateCollection certificate = new X509CertificateCollection();
certificate.Add(cert);
  • 然后,传递主机地址和端口,创建一个SslStream实例,并且握手,代码如下:
//发布模式, 主机地址是 gateway.push.apple.com    
//开发模式, 主机地址是 gateway.sandbox.push.apple.com
TcpClient client = new TcpClient("gateway.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(_host, certificate, SslProtocols.Default, false);
}
catch (Exception e)
{
    Console.WriteLine("Exception Message: {0} ", e.Message);
    sslStream.Close();
}

//这是握手后的回调
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;
}
  • 构建payload字符串,发送远程通知
//PushNotificationPayload是一个结构体的定义 
public struct PushNotificationPayload
{
    public string deviceToken;
    public string message;
    public string sound;
    public int badge;

    public string PushPayload()
    {
        return "{\"aps\":{\"alert\":\"" + message + "\",\"badge\":" + badge + ",\"sound\":\"" + sound + "\"}}";
    }
}

//把值赋给payload
PushNotificationPayload payload = new PushNotificationPayload();
payload.deviceToken = "dc67b56c eb5dd9f9 782c37fd cfdcca87 3b7bc77c 3b090ac4 c538e007 a2f23a24";
payload.badge = 56789;
payload.sound = "default";
payload.message = "This message was pushed by C# platform.";

//然后调用Push()方法
public void Push(PushNotificationPayload payload)
{
    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();
}

好了,就是这么简单,如果有疑问,欢迎在github上提问。
高手请略过


标签:Apple,C#,Notification,writer,System,APNs,通知,payload,字节
From: https://blog.51cto.com/u_14062833/6320540

相关文章

  • 深入理解Spring MVC:Java Web 开发的强大框架
    简介:SpringMVC是一个基于Java的开源Web应用框架,它提供了一种基于模型-视图-控制器(Model-View-Controller)设计模式的开发方式。它是Spring框架的一部分,用于构建高度可扩展的Web应用程序。本博客将深入探讨SpringMVC的核心概念和特性,以及如何使用它构建灵活、可维护的......
  • Oracle与DB2、MySQL取前10条记录的对比
    Oralce的示例:1.最佳选择:利用分析函数row_number()over(partitionbycol1orderbycol2)比如想取出100-150条记录,按照tname排序selecttname,tabtypefrom(selecttname,tabtype,row_number()over(orderbytname)rnfromtab)whe......
  • c++宏
    _Pragmaonce操作符#pragma是一条预处理指令,简单的说他是用来向编译器传达语言标注以外的一些信息例如我们在头文件中定义了如下语句#pragmaonce则表示该指令会指示编译器该头文件只会被编译一次(保证头文件只被include一次)而c++11中定义了与#pragma功能相同的操作符_Pgram......
  • OPENCV3.0的配置
    目前网上关于opencv3.0的配置参差不齐,要么就直接导致失败,要么是配置过于复杂,这里笔者从减少工作量出发从配置说起首先是系统环境变量的添加 ==================》=================>>==============================>>===========>>新建一个变量名为PATH的环境变量,之后变量值定位......
  • 使UIScrollView的子控件在scrolling的过程中,子控件不滚动(固定在某个位置)
    使UIScrollView的子控件在scrolling的过程中,子控件不滚动(固定在某个位置)受本篇问答的启发http://stackoverflow.com/questions/11272847/make-uiview-in-uiscrollview-stick-to-the-top-when-scrolled-up修改代码如下注意:使UIScrollView的子控件self.letter在scrolling的过程中,子......
  • 使用 @GrpcClient 实现客户端
    转载请注明出处:@GrpcClient注解的作用是将gRPC客户端注入到Spring容器中,方便在应用程序中使用gRPC客户端调用gRPC服务提供的函数。使用@GrpcClient注解,我们可以像使用其他SpringBean一样来使用gRPC客户端,无需手动创建连接通道和stub类对象,SpringBoot会自......
  • webpack-指定webpack的entry和output
    webpack中的默认约定在webpack4.x和5.x的版本中,有如下的默认约定:默认的打包入口文件为src->index.js默认的输出文件路径为dist->main.js注意:可以在webpack.config.js中修改打包的默认约定自定义打包的入口和出口在webpack.config.js配置文件中,通过entry节点指定打包的入口......
  • 【Linux】信号 —— 信号的产生 | 信号的保存 | 信号的处理 | volalite关键字 | SIGCH
    信号1.信号的产生-信号发送前1.1键盘产生1.2异常1.3系统调用1.4软件条件1.5理解发送信号2.信号的保存-信号发送中2.1相关概念&内核结构2.2sigset_t及一系列系统调用函数3.信号的处理-信号发送后3.1内核如何实现信号捕捉3.2sigaction4.可重入函数5.volalite......
  • 03、Etcd 客户端常用命令
    上一讲我们安装etcd服务端,这一讲我们来一起学学如何使用etcd客户端常见的命令。文章内容来源于参考资料,如若侵权,请联系删除,谢谢。etcd可通过客户端命令行工具etcdctl对etcd进行请求操作#帮助命令,会列出所有的命令和选项,在记不太清命令的时候,可以使用etcdctl‐h#......
  • centos7 中如何同步时间
     001、查看时区[root@PC1bin]#timedatectlstatus|grep'Timezone'Timezone:Asia/Shanghai(CST,+0800) 002、查看当前时间[root@PC1bin]#dateMonMay2201:15:22CST2023 003、安装ntpdate[root@PC1bin]#yum-yinstallntpdate 004......