本文目的:向Remoting在线客户端广播消息。
使用的主要技术:异步,回调,广播。
实现过程:
定义远程实例
using System; using System.Collections.Generic; using System.Text; using System.Runtime.Remoting.Messaging; namespace RemoteObject { //定义委托,显示回调消息 public delegate void ShowCallBackMsg(string str1,string str2); //在客户端生成的远程实例,供服务端调用回调 public class OnLineCallBack:MarshalByRefObject { //客户端实现委托的方法 public ShowCallBackMsg ShowMsg; //供服务端调用回调 public void CallBack(string str1, string str2) { if (ShowMsg != null) { ShowMsg.Invoke(str1, str2); } } } //在服务端运行的远程实例 public class RemoteObject:MarshalByRefObject { //静态变量 记录每个客户端生成供回调的远程实例 public static List<OnLineCallBack> ListOnline = new List<OnLineCallBack>(); public RemoteObject() { } //添加用户端生成供回调的远程实例 public void AddOnlineCallBack(OnLineCallBack xCallBack) { ListOnline.Add(xCallBack); } //使用OneWay,异步执行,客户端发出执行命令,即不再等待返回,交由服务端回调处理 [System.Runtime.Remoting.Messaging.OneWay] public void DoSomething(string str1, string str2, int isleep) { //为看效果,等待时长 System.Threading.Thread.Sleep(isleep); //将所有登记的在线远程实例执行回调,广播消息 foreach (OnLineCallBack xCallBack in ListOnline) { xCallBack.CallBack(str1, str2); } } } }
服务端:
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels ; using System.Runtime.Remoting.Channels.Tcp ; namespace RemoteServer { public partial class Form1 : Form { public Form1() { InitializeComponent(); } TcpChannel chan1; private void button1_Click(object sender, EventArgs e) { //启动服务端 try { IDictionary tcpProperties = new Hashtable(); tcpProperties["name"] = "RemoteTest"; //指定服务端口 tcpProperties["port"] = int.Parse(textBox1.Text); BinaryClientFormatterSinkProvider tcpClientSinkProvider = new BinaryClientFormatterSinkProvider(); BinaryServerFormatterSinkProvider tcpServerSinkProvider = new BinaryServerFormatterSinkProvider(); tcpServerSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; chan1 = new TcpChannel(tcpProperties, tcpClientSinkProvider, tcpServerSinkProvider); ChannelServices.RegisterChannel(chan1); RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteObject.RemoteObject), "RemoteTest", WellKnownObjectMode.Singleton); MessageBox.Show("Start Success!"); button1.Enabled = false ; button2.Enabled = true ; } catch (Exception ex) { MessageBox.Show(ex.Message); } } //停止服务端 private void button2_Click(object sender, EventArgs e) { try { if (chan1 != null) { ChannelServices.UnregisterChannel(chan1); } } catch (Exception ex) { MessageBox.Show(ex.Message); } button1.Enabled = true; button2.Enabled = false; } } }
客户端
using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Services; using System.Runtime.Remoting.Channels.Tcp; namespace RemoteClient { public partial class Form1 : Form { public Form1() { InitializeComponent(); } TcpChannel chan1 = null; RemoteObject.RemoteObject obj1 = null; private void btnConnect_Click(object sender, EventArgs e) { //连接服务端 try { IDictionary tcpProperties = new Hashtable(); BinaryClientFormatterSinkProvider tcpClientSinkProvider = new BinaryClientFormatterSinkProvider(); BinaryServerFormatterSinkProvider tcpServerSinkProvider = new BinaryServerFormatterSinkProvider(); tcpServerSinkProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; //为防止客户端有多个网卡IP,指定使用可以与服务端通信的IP if (btnBindIp.Text.Trim().Length > 0) tcpProperties["bindTo"] = btnBindIp.Text; tcpProperties["timeout"] = 5; //这个很关键,为0表示侦听所有的端口,是接收服务端回调的必要条件 tcpProperties["port"] = 0; chan1 = new TcpChannel(tcpProperties, tcpClientSinkProvider, tcpServerSinkProvider); //注册通信管道 ChannelServices.RegisterChannel(chan1); obj1 = (RemoteObject.RemoteObject)Activator.GetObject( typeof(RemoteObject.RemoteObject), "tcp://" + txtSrvIP.Text + ":" + txtSrvPort.Text + "/RemoteTest"); //生成供服务端回调的客户端远程实例 RemoteObject.OnLineCallBack xCallBack = new RemoteObject.OnLineCallBack(); //指定接收处理服务端回调的方法 xCallBack.ShowMsg = new RemoteObject.ShowCallBackMsg(xCallBack_ShowMsg); //调用服务端远程方法AddOnlineCallBack,记录客户端远程实例 obj1.AddOnlineCallBack(xCallBack); btnConnect.Enabled = false; btnInvoke.Enabled = true; } catch (Exception ex) { MessageBox.Show(ex.Message); btnConnect.Enabled = true; btnInvoke.Enabled = false; } } private void btnBreak_Click(object sender, EventArgs e) { try { //断开连接 ChannelServices.UnregisterChannel(chan1); obj1 = null; } catch (Exception ex) { MessageBox.Show(ex.Message); } btnConnect.Enabled = true; btnBreak.Enabled = false; } private void btnInvoke_Click(object sender, EventArgs e) { try { //调用服务端RemoteObject的远程方法(其方法是OneWay的异步模式) obj1.DoSomething("AAA", "BBB", 5000); } catch (Exception ex) { MessageBox.Show(ex.Message); } } //处理服务端回调消息的方法 void xCallBack_ShowMsg(string str1, string str2) { MessageBox.Show(str1 + str2); } } }