很多时候我们会遇到,信息及时推送通知的情况,例如:监控设备时及时推送状态、报警信息等,我们就可以用WCF的回调机制来实现,下面以一个监控设备名字为例,如果设备名字发生改变,服务器就马上推送消息给客户端:
(一、)服务器端
1、建一个控制台应用程序:CallbackContractWCF
2、创建ISendMessage接口
namespace CallbackContractWCF { [ServiceContract(CallbackContract = typeof(IMessageCallbackContract))] public interface ISendMessage { /// /// 保存客户端回调的实例 /// [OperationContract] void Subscribe(); } }
3、创建用于推送消息回调的接口IMessageCallbackContract
namespace CallbackContractWCF { public interface IMessageCallbackContract { [OperationContract(IsOneWay = true)] void ReportMes(string responseToGreeting); } }
4、创建实现接口ISendMessage的类SendMessage
1 namespace CallbackContractWCF 2 { 3 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple,UseSynchronizationContext=false)] 4 public class SendMessage:ISendMessage 5 { 6 private System.Timers.Timer _setValueTimer; 7 private IMessageCallbackContract callerProxy = null; 8 ~SendMessage() 9 { 10 _setValueTimer.Stop(); 11 Device.OnChange -= new Action(Student_OnChange); 12 } 13 public SendMessage() 14 { 15 Thread.Sleep(3000); 16 _setValueTimer = new System.Timers.Timer(); 17 _setValueTimer.AutoReset = true; 18 _setValueTimer.Elapsed += Timer_Elapsed; 19 _setValueTimer.Interval = 10000; 20 _setValueTimer.Start(); 21 Device.OnChange += new Action(Student_OnChange); 22 } 23 //保存客户端回调的实例 24 public void Subscribe() 25 { 26 try 27 { 28 //获取当前调用的核心服务端实例的通道 29 callerProxy = OperationContext.Current.GetCallbackChannel(); 30 } 31 catch (Exception ex) 32 { 33 throw new FaultException(ex.Message); 34 } 35 } 36 private void Timer_Elapsed(object sender, ElapsedEventArgs e) 37 { 38 Random rand = new Random(); 39 string name = "路由器"+rand.Next(10); 40 SetName(name); 41 } 42 private void SetName(string greeting) 43 { 44 if (greeting != Device.Name) 45 { 46 Device.Name = greeting; 47 Device.Change(greeting); 48 } 49 } 50 void Student_OnChange(string name) 51 { 52 try 53 { 54 Console.Write("只要名字与当前的不同就向客户端推送通知 "); 55 callerProxy.ReportMes(name); 56 } 57 catch (Exception ex) 58 { 59 Console.Write(ex.Message); 60 } 61 } 62 } 63 //创建设备类 64 public static class Device 65 { 66 public static string Name { get; set; } 67 public static event Action OnChange; 68 public static void Change(string name) 69 { 70 if (OnChange != null) 71 { 72 OnChange.Invoke(name); 73 } 74 } 75 } 76 }
5、添加配置文件App.config
<configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="behavior1"> <serviceMetadata httpGetEnabled="false" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="BigBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288000" maxBufferSize="65536000" maxConnections="10" maxReceivedMessageSize="65536000"> <readerQuotas maxDepth="32000" maxStringContentLength="8192000" maxArrayLength="16384000" maxBytesPerRead="4096000" maxNameTableCharCount="16384000"/> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/> <security mode="None"/> </binding> <binding name="netTcpBinding_ISendMessage"> <security mode="None"></security> </binding> </netTcpBinding> </bindings> <services> <service name="CallbackContractWCF.SendMessage" behaviorConfiguration="behavior1"> <endpoint address="SendMessage" binding="netTcpBinding" bindingConfiguration="BigBinding" contract="CallbackContractWCF.ISendMessage" name="netTcpBinding_ISendMessage" > <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:8729/Design_Time_Addresses/CallbackContractWCF/SendMessage/" /> </baseAddresses> </host> </service> </services> </system.serviceModel> </configuration>
(二、)客户端
1、创建控制台应用程序CallbackContractClient
2、启动服务器,添加服务引用
3、创建一个实现服务器端回调接口的类MessageCallback
namespace CallbackContractClient { [System.ServiceModel.CallbackBehavior(IncludeExceptionDetailInFaults = true, UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)] public class MessageCallback : ISendMessageCallback { public event Action OnReportMes; //实现服务端的回调 public void ReportMes(string responseMes) { if (OnReportMes != null) { OnReportMes.Invoke(responseMes); } } } }
4、在控制台主程序Program.cs中挂载服务
namespace CallbackContractClient { class Program { static void Main(string[] args) { MessageCallback callback=new MessageCallback (); callback.OnReportMes+=new Action(callback_OnReportMes); InstanceContext content = new InstanceContext(callback); SendMessageClient clicent = new SendMessageClient(content); clicent.Subscribe(); Console.Write("监控设备"); Console.ReadLine(); } public static void callback_OnReportMes(string res) { Console.Write(" 设备的名称为:" + res); Console.ReadLine(); } } }
(三、)监测结果