1.协议

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;namespace WCFHub.IService
{[ServiceContract(CallbackContract=typeof(IEventCallback))]public interface IEventService{[OperationContract(IsOneWay = true)]void Subscribe(SubscribeArg a);[OperationContract(IsOneWay = true)]void Unsubscribe(ArgumentBase<String> a);[OperationContract]DateTime Ping();}public interface IEventCallback{[OperationContract(IsOneWay = true)]void OnMessageReceived(ArgumentBase<String> a);}
}

View Code

2.实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.ServiceModel;
using System.ServiceModel.Channels;namespace WCFHub.IService
{public class EventServiceImpl:IEventService{public static readonly ConcurrentDictionary<String, SubscribeContext> _Subscribers = new ConcurrentDictionary<String, SubscribeContext>();public string ClientIpAndPort(){OperationContext context = OperationContext.Current;MessageProperties properties = context.IncomingMessageProperties;RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;return endpoint.Address + ":" + endpoint.Port.ToString();}public void Subscribe(SubscribeArg a){Console.WriteLine(ClientIpAndPort());var callback  = OperationContext.Current.GetCallbackChannel<IEventCallback>();a.Username=a.Username.ToLower();_Subscribers[a.Username]=new SubscribeContext(){Arg=a,Callback=callback};#region 事件处理ICommunicationObject obj = (ICommunicationObject)callback;obj.Closed += (s,e) =>{Console.WriteLine("Closed");};obj.Faulted += (s, e) => {Console.WriteLine("Faulted");};obj.Closing += (s,e) => {Console.WriteLine("Closeing" + OperationContext.Current);var callback2=(IEventCallback)s;_Subscribers.ToList().ForEach(ent => {if (ent.Value.Callback == callback2){RemoveSubscriber(ent.Value.Arg.Username);}});};#endregion}public void Unsubscribe(ArgumentBase<string> a){RemoveSubscriber(a.Model);}private static void RemoveSubscriber(string username){username = username.ToLower();if (_Subscribers.ContainsKey(username)){SubscribeContext outObj = null;_Subscribers.TryRemove(username, out outObj);}}public static void PostData(ArgumentBase<string> a){Console.WriteLine("收到待发消息:" + a.Model);_Subscribers.ToList().ForEach(subscriber =>{ICommunicationObject callback = (ICommunicationObject)subscriber.Value.Callback;if (((ICommunicationObject)callback).State == CommunicationState.Opened){try{//此处需要加上权限判断、订阅判断等
                       subscriber.Value.Callback.OnMessageReceived(a);}catch (Exception ex){RemoveSubscriber(subscriber.Value.Arg.Username);Console.WriteLine("PostData:" + ex.Message);}}else{RemoveSubscriber(subscriber.Value.Arg.Username);Console.WriteLine("PostData,用户链接已经关闭");}});}#region IEventService 成员public DateTime Ping(){Console.WriteLine("Ping:" + ClientIpAndPort() +"," +DateTime.Now);return DateTime.Now;}#endregion}public class SubscribeContext{public SubscribeArg Arg { get; set; }public IEventCallback Callback { get; set; }}
}

View Code

3.实体类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace WCFHub.IService
{[Serializable]public class ArgumentBase<T>{private int code;private string msg;private T model;public int Code{get { return code; }set { code = value; }}public string Msg{get { return msg; }set { msg = value; }}public T Model{get { return model; }set { model = value; }}}public class SubscribeArg : ArgumentBase<int>{public String Username { get; set; }public List<int> Alarms { get; set; }public SubscribeArg(){Alarms = new List<int>();}}
}

View Code

4.服务托管

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using WCFHub.IService;namespace WCFHub.Win
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private ServiceHost _Host = new ServiceHost(typeof(EventServiceImpl));private void Form1_Load(object sender, EventArgs e){_Host.AddServiceEndpoint(typeof(IEventService), new NetTcpBinding(SecurityMode.None),"net.tcp://192.168.30.30:9999/EventService");_Host.Open();Console.WriteLine("服务开启...");}protected override void OnClosed(EventArgs e){_Host.Close();base.OnClosed(e);Console.WriteLine("服务关闭!");}private void button1_Click(object sender, EventArgs e){var data = new ArgumentBase<string>() { Model = textBox1.Text + "," + DateTime.Now.ToString() };EventServiceImpl.PostData(data);}}
}

View Code

5.客户端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WCFHub.IService;
using System.ServiceModel;
using System.Threading;namespace WCFHub.WinClient
{#region MessageReceivepublic delegate void MessageReceivedHandle(ArgumentBase<string> a);public class NotifyManager : IEventCallback{public event MessageReceivedHandle MessageReceived;public static int C_MaxErrCount = 5;public static int C_HeartbeatInterval = 1000 * 10;//10秒一次心跳检测IEventService _Proxy = null;private int ErrCounter = 0;public bool Enabled { get; set; }public NotifyManager(){Enabled = false;}private void Close(){if (_Proxy != null){try{var comObj = _Proxy as ICommunicationObject;comObj.Abort();}catch { }}}public void Start(){Enabled = true;StartInternal();#region 心跳检测var timer = new System.Timers.Timer();timer.Enabled = false;timer.Interval = C_HeartbeatInterval;timer.Elapsed += (s, ie) =>{try{WriteLine("心跳检测...");timer.Enabled = false;_Proxy.Ping();ErrCounter = 0;}catch (Exception ex){WriteLine(ex.Message);ErrCounter++;if (ErrCounter >= C_MaxErrCount){Close();StartInternal();}}finally{timer.Enabled = true;}};timer.Start();#endregion}private void StartInternal(){if (!Enabled) return;lock (this){try{#regionErrCounter = 0;_Proxy = WCFHelper.Factory.CreateChannel(new InstanceContext(this));var comObj = _Proxy as ICommunicationObject;comObj.Faulted += (s, ie) =>{WriteLine("Faulted");};comObj.Closed += (s, ie) =>{WriteLine("Closed!");};comObj.Closing += (s, ie) =>{WriteLine("Closing!");};WriteLine("加载并配置完成!");_Proxy.Subscribe(new SubscribeArg() { Username = Guid.NewGuid().ToString("N") });WriteLine("注册成功!");#endregion}catch (Exception ex){WriteLine(ex.Message);}}}public void Stop(){Enabled = false;Close();}public void WriteLine(string msg){Console.WriteLine(msg + "," + DateTime.Now);}#region IEventCallback 成员public void OnMessageReceived(ArgumentBase<string> a){if (MessageReceived != null){MessageReceived(a);}}#endregion}#endregionpublic partial class Form1 : Form{private SynchronizationContext SyncContext = null;public Form1(){InitializeComponent();SyncContext = SynchronizationContext.Current;}NotifyManager _NotifyManager = null;private void Form1_Load(object sender, EventArgs e){_NotifyManager = new NotifyManager();_NotifyManager.MessageReceived += OnMessageReceived;_NotifyManager.Start();}protected override void OnClosed(EventArgs e){if (_NotifyManager != null){_NotifyManager.MessageReceived -= this.OnMessageReceived;_NotifyManager.Stop();}base.OnClosed(e);}public void OnMessageReceived(ArgumentBase<string> a){Console.WriteLine("收到消息:" + a.Model +",InvokeRequired:" + this.InvokeRequired);if (this.InvokeRequired){SyncContext.Post((d) =>{textBox1.Text += a.Model + Environment.NewLine;}, null);}else{textBox1.Text += a.Model + Environment.NewLine;}}private void button1_Click(object sender, EventArgs e){if (_NotifyManager != null){Console.WriteLine((_NotifyManager as ICommunicationObject).State);}}}public class WCFHelper{private static DuplexChannelFactory<IEventService> _channelFac;public static DuplexChannelFactory<IEventService> Factory{get{if (_channelFac == null){_channelFac =new DuplexChannelFactory<IEventService>(typeof(NotifyManager), new NetTcpBinding(SecurityMode.None),EndpointStr);}return _channelFac;}}private static string EndpointStr{get{return "net.tcp://192.168.30.30:9999/EventService";}}}
}

View Code

使用WCF实现消息推送相关推荐

  1. iOS消息推送机制的实现

    iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务 ...

  2. 未读消息(小红点),前端 与 RabbitMQ 实时消息推送实践,贼简单~

    前几天粉丝群里有个小伙伴问过:web 页面的未读消息(小红点)怎么实现比较简单,刚好本周手头有类似的开发任务,索性就整理出来供小伙伴们参考,没准哪天就能用得上呢. 之前在 <springboot ...

  3. 友盟小米收不到推送消息_Android 手机收不到消息推送的设置指南 - 融云 RongCloud...

    如何解决 Android 手机因推送权限问题收不到消息提醒? 问题描述 部分 Android 手机系统在黑屏待机后自动清理后台运行的软件,这样影响了应用正常接收新的消息,需要开启手机的某些权限.此文档 ...

  4. iOS 消息推送原理及实现总结

    一.消息推送原理: 在实现消息推送之前先提及几个于推送相关概念,如下图: 1. Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Prov ...

  5. 安卓消息推送解决方案

    一.推送工具使用 我们在做安卓开发的时候,通常需要一些消息推送功能,我个人平时用的是极光推送,极光推送(JPush)是一个端到端的推送服务,使得服务器端消息能够及时地推送到终端用户手机上,让开发者积极 ...

  6. 细说 iOS 消息推送

    APNS的推送机制 与Android上我们自己实现的推送服务不一样,Apple对设备的控制很严格.消息推送的流程必需要经过APNs: 这里 Provider 是指某个应用的Developer,当然假设 ...

  7. Asp.net SignalR 实现服务端消息推送到Web端

    参考博客https://www.cnblogs.com/wintersun/p/4148223.html ASP .NET SignalR是一个ASP .NET 下的类库,可以在ASP .NET 的W ...

  8. 【iOS学习笔记】IOS开发中设置applicationIconBadgeNumber和消息推送

    因为在IOS8中要想设置applicationIconBadgeNumber,需要用户的授权,在IOS8中,需要加上下面的代码: UIUserNotificationSettings *setting ...

  9. Android socket 编程 实现消息推送(二)

    上篇文章Android socket 编程 实现消息推送(一)讲到socket编程的消息推送原理,现在我们来看看基于Android客户机socket编程实现消息推送的过程. 根据消息推送的原理图,我们 ...

最新文章

  1. Python Django URL传参代码示例
  2. python将列表写入csv_转:Python 将列表数据写入文件(txt, csv, excel)
  3. POJ 2227 The Wedding Juicer——堆的应用——Pku2227
  4. mysql创建虚拟网卡_创建启动虚拟网卡
  5. 开源WEB服务器-lighttpd 1.4.24发布
  6. 5G仿真-蒙特卡洛仿真方法
  7. mysql双机热备份
  8. 2022年最新版初级商业数字营销师直通车题库
  9. python语音合成并播放_用Python写一个语音播放软件
  10. python爬取网易云音乐评论并进行情感分析_使用python3爬取网易云音乐的评论
  11. ping-pong机制
  12. 教你如何写出高效整洁的 css 代码——css优化(转载)
  13. CSS 单(多)行文本超过部分显示省略号,解决数字或英文不换行问题
  14. 新增免费 代理(Proxy)验证助手 自用 支持http/socks
  15. ABP理论学习之本地化
  16. 科学计算机sd mode使用方法,你是否知道科学计算器的使用方法
  17. C#中BackgroundImage与Image的区别
  18. Gradle系列【2】Groovy基础语法篇
  19. C++类成员函数作回调函数
  20. 虚拟化服务器和存储关系,虚拟化服务器和云存储的对比

热门文章

  1. LINUX/CentOS防CC***脚本
  2. 11个恶意python包被指窃取 Discord 令牌、安装shell
  3. 接口,实现类,对象方法的调用关系.(查看程序输出)
  4. vue源码解析推荐文章
  5. 音效SystemSoundID
  6. linux IPv4报文处理浅析
  7. 不重启程序使用最新版package
  8. python替换UTF-8编码文本中任意特殊字符,包括中文符号问题:大量文本,将其中的特殊字符用空
  9. python实现批量转换文件编码(批转换编码示例)
  10. Ubuntu 开发者工具中心 Ubuntu Make