• 使用WCF实现消息推送


    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 MessageReceive
        public 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
                    {
                        #region
                        ErrCounter = 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
        }
        #endregion
    
        public 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
  • 相关阅读:
    NTC温度检测程序(转)
    基于GPS的经纬度、方位角、距离、航向计算及基于单目视觉的距离计算!
    GPS速度和航向计算(转)
    NOR、 NAND、Raw Flash和 Managed Flash的区别(转)
    FreeModbus V1.6 主机使用说明(转)
    只要单片机具有真正唯一ID,就可以让加密坚不可摧(转)
    Java 给Word添加数字签名
    Java 获取Word中指定图片的坐标位置
    C#/VB.NET 自定义PPT动画路径
    在线编辑Excel——插入图表
  • 原文地址:https://www.cnblogs.com/wdfrog/p/3924718.html
Copyright © 2020-2023  润新知