.Net Remoting 应用实例 DotNetRemotingChat
来源:互联网 发布:淘宝直通车排序 编辑:程序博客网 时间:2024/05/19 12:12
最近研究了一下.Net Remoting技术,做了个实例,简单记录下来,以便参考。
概念性的东西不多说了,前面也转载了几篇文章,写的都不错,这里主要说说我的这个实例的实现过程。
这个实例包含三个项目:Chat_Server,Chat_Client,Chat_CommonLib,即服务端,客户端和公共程序集,一般.Net Remoting都包含这三块。
先来看看Chat_CommonLib项目,该项目是一个类库程序,包含两个接口IRemoteObjectFactory,IRemoteObject,一个类EventWrapper和一个公共委托MessagedEventHandler。
namespace Chat_CommonLib{ public interface IRemoteObjectFactory { IRemoteObject CreateInstance(string user); }}
namespace Chat_CommonLib{ public delegate void MessagedEventHandler(string msg); public interface IRemoteObject { string User { get; set; } void Connect(); void Disconnect(); void SendMessage(string msg); void SubMessage(string msg); event MessagedEventHandler Messaged; }}
namespace Chat_CommonLib{ public class EventWrapper:MarshalByRefObject { public event MessagedEventHandler Messaged; public void SubMessage(string msg) { if (Messaged != null) { MessagedEventHandler temp = null; foreach (Delegate del in Messaged.GetInvocationList()) { try { temp = (MessagedEventHandler)del; temp(msg); } catch (Exception ex) { //RemoteObjectFactory.SubLogger("Send event message fail.\r\n" + ex.ToString()); } } } } public override object InitializeLifetimeService() { return null; } }}
在服务端实现远程对象,注意远程对象及其工厂都要继承MarshalByRefObject,并实现先前定义的接口
namespace Chat_Server.Codes{ class RemoteObjectFactory : MarshalByRefObject, IRemoteObjectFactory { public static event Action<string> Logger; public static List<IRemoteObject> RemoteObjects = new List<IRemoteObject>(); public IRemoteObject CreateInstance(string user) { IRemoteObject remoteObject = new RemoteObject(user); RemoteObjects.Add(remoteObject); return remoteObject; } public static void SubLogger(string msg) { if (Logger != null) { Logger(msg); } } public static void SendMessage(IRemoteObject user, string msg) { user.SubMessage(msg); } public static void SendMessage(IRemoteObject user, string msg, bool self) { foreach (IRemoteObject _user in RemoteObjects) { if (_user != user || self) { SendMessage(_user, msg); } } } public override object InitializeLifetimeService() { return null; } }}
namespace Chat_Server.Codes{ class RemoteObject : MarshalByRefObject, IRemoteObject { public event MessagedEventHandler Messaged; private string mUser; public string User { get { return mUser; } set { mUser = value; } } public RemoteObject(string user) { mUser = user; } public void Connect() { string msg = string.Format("{0}\tConnected.", mUser); RemoteObjectFactory.SubLogger(msg); RemoteObjectFactory.SendMessage(this, "Server connected."); RemoteObjectFactory.SendMessage(this, msg, false); } public void Disconnect() { string msg = string.Format("{0}\tDisconnected.", mUser); RemoteObjectFactory.RemoteObjects.Remove(this); } public void SubMessage(string msg) { if (Messaged != null) { MessagedEventHandler temp = null; foreach (Delegate del in Messaged.GetInvocationList()) { try { temp = (MessagedEventHandler)del; temp(msg); } catch (Exception ex) { RemoteObjectFactory.SubLogger("Send event message fail.\r\n" + ex.ToString()); } } } } public override object InitializeLifetimeService() { return null; } public void SendMessage(string msg) { RemoteObjectFactory.SendMessage(this, this.User + "\t" + msg, true); } }}
注册通道,我这里采用服务端SingleTon激活方式,但是功能上看类似于客户端激活方式,因为远程对象实在客户端实例化的,并且每个客户端独立使用一个远程对象。
服务端通道注册:
private bool CreateRemoteObject() { try { SoapServerFormatterSinkProvider soap = new SoapServerFormatterSinkProvider(); BinaryServerFormatterSinkProvider binary = new BinaryServerFormatterSinkProvider(); soap.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; binary.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; soap.Next = binary; Hashtable table = new Hashtable(); table.Add("port", II_ServerPort); TcpChannel channel = new TcpChannel(table, null, soap); ChannelServices.RegisterChannel(channel, false); RemotingConfiguration.ApplicationName = "RemotingChat"; RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObjectFactory), "RemotingChat", WellKnownObjectMode.Singleton); } catch (Exception ex) { IS_Error = ex.ToString(); return false; } return true; }
客户端通道注册及远程对象的激活:
private bool MakeConnection() { try { SoapServerFormatterSinkProvider soap = new SoapServerFormatterSinkProvider(); BinaryServerFormatterSinkProvider binary = new BinaryServerFormatterSinkProvider(); soap.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; binary.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; soap.Next = binary; Hashtable table = new Hashtable(); table.Add("port", "0"); TcpChannel channel = new TcpChannel(table, null, soap); ChannelServices.RegisterChannel(channel, false); string url = string.Format("tcp://{0}:{1}/RemotingChat", IS_ServerIP, II_ServerPort); IRemoteObjectFactory objectFactory = (IRemoteObjectFactory)Activator.GetObject(typeof(IRemoteObjectFactory), url); I_RemoteObject = objectFactory.CreateInstance(GetCurrentIP()); EventWrapper eventWrapper = new EventWrapper(); eventWrapper.Messaged += new MessagedEventHandler(eventWrapper_Messaged); I_RemoteObject.Messaged += new MessagedEventHandler(eventWrapper.SubMessage); I_RemoteObject.Connect(); } catch (Exception ex) { IS_Error = ex.ToString(); return false; } return true; }
主要代码就如以上所述,下面重点说说其中要注意的几点:
1、工厂模式,工厂模式是一种极为常见的编程方式,其核心就一个CreateInstance方式,能够返回指定类型的实例,在这个实例中RemoteObject就工厂RemoteObjectFactory返回的一个对象,可以在客户端调用这个方法。
2、代码组织,由于远程对象在服务端和客户端都要引用,一个好的办法就是利用接口,在接口中定义远程对象的各个方法事件等,在服务端具体实现,而客户端只需引用对应的接口就行,并且接口和其他可能需要封送的的类都放在公共程序集中,这样代码更加清晰,引用也方便。
3、远程对象事件及事件的订阅,这是最难也是最容易出错的地方,尤其客户端订阅服务端事件。客户端是通过代理引用远程对象的,因而客户端引用的并不是真正的远程对象,而是其代理,所以对其订阅事件并不能这真订阅到远程对象本身。一个好的办法就是包装事件,即设计一个事件包装器类EventWrapper,其中的事件和远程对象的定义样,这个类还必须继承MarshalByRefObject以实现远程封送,通过这个中间类可以实现客户端订阅服务端事件。
- .Net Remoting 应用实例 DotNetRemotingChat
- C#.net,remoting的简单应用实例
- .Net Remoting 实例
- .net Remoting简单实例
- .net Remoting简单实例
- .net Remoting简单实例
- .Net Remoting 实例
- 实例解析.net remoting 技术要点
- 简单学会.net remoting,基础讲解+实例
- .Net中Remoting通信机制简单实例
- .NET Remoting来开发分布式应用初步
- C# .NET Remoting 简单应用示例
- WindowsService+.Net Remoting 实现分布式应用系统
- 初识用.NET Remoting开发分布式应用
- .Net中Remoting技术应用简述
- .NET Remoting与分布式应用开发
- [Remoting] 一:.NET Remoting
- [Remoting] 一:.NET Remoting
- 二叉树笔记-理论篇
- MyEclipse下项目的包层次结构问题
- 怎么封QQ?
- 给中国铁路售票系统的一点点意见
- 堆,栈,代码段,数据段,BSS 段概念解析
- .Net Remoting 应用实例 DotNetRemotingChat
- Android实现两次按下返回键退出
- Sizeof与字符串
- hdu 3507 Print Article(DP+斜率优化)
- Apache Tomcat 数据源密码加密(c3p0)
- 计算机日常操作
- 成功创业不可不知8个箴言
- 关于C++ const 的全面总结
- qt多线程