Microsoft .Net Remoting系列教程之一-.Net Remoting基础篇
一、走进Remoting的世界
Remoting,一个藏于微软.Net平台下的分布式处理宝藏。它是DCOM的升级版本,不仅优化了众多功能,还完美融入了.Net生态系统。简单来说,Remoting允许我们通过特定的框架,在一个应用程序域与另一个应用程序域之间传递对象,实现跨域通信。在Windows操作系统中,每一个应用程序都被隔离成单独的运行进程,形成了一个保护机制,防止数据在不同进程间随意流通。但在某些场景下,我们需要跨越这道边界,与不同的应用程序域进行对话。这时候,Remoting就派上了用场。
Remoting中的通信桥梁——通道(channel)
在Remoting的世界里,通道是连接两个应用程序域的桥梁。这个桥梁通过特定的协议(如Tcp或Http)来传递信息。客户端通过Remoting连接到通道,获取服务端对象的引用。这些对象在服务器端运行,但通过序列化过程,在客户端以另一种形式展现。这就为服务发布提供了一个便捷的机制。远程对象可以在服务器端激活,然后客户端通过Remoting连接服务器,获取并使用这个对象。
Remoting的两大通道类型:Tcp与Http
在.Net中,定义了IChannel接口,其中包含了两种主要的通道类型:TcpChannel和HttpChannel。TcpChannel基于Socket工具,使用Tcp协议进行数据传输,它在局域网内具有更高的传输性能。而HttpChannel则通过Http协议传输数据,能在防火墙环境下轻松传输序列化消息流。在穿越防火墙的场景下,HttpChannel由于其良好的互操作性而更受欢迎。
远程对象的激活之旅
在访问远程对象之前,需要通过一个名为Activation的过程创建并初始化这个对象。这个过程被称为对象的激活。在Remoting中,远程对象的激活分为服务器端激活和客户端激活两种方式。服务器端激活又称为WellKnow方式或知名对象激活模式。服务器应用程序会在一个统一的资源标识符上发布这个对象的类型,并根据指定的端口或地址来发布对象实例。这种激活模式分为SingleTon模式和SingleCall模式。SingleTon模式为有状态模式,为所有客户端创建并维护同一个对象实例;而SingleCall模式则为每个客户端请求创建一个新的对象实例。
Remoting是一个强大的跨域通信工具,它允许我们在不同的应用程序域之间传递对象,实现数据的自由流通。通过Tcp和Http两种通道,我们可以轻松穿越防火墙和数据边界,实现数据的共享和服务的发布。无论是服务器端激活还是客户端激活,都能满足不同的需求场景,确保数据的正确传输和处理。深入SingleCall模式和客户端激活在Remoting中的特性
一、SingleCall模式与客户端激活概述
在分布式应用程序中,对象远程访问是一个核心问题。在Remoting中,对象的访问模式主要有两种:SingleCall模式和客户端激活模式。SingleCall模式是一种无状态模式,为每个客户端调用创建一个新的远程对象实例。而客户端激活模式则为每个客户端请求创建一个持久的远程对象实例。深入理解这两种模式的特点对于开发高效的分布式应用至关重要。
二、SingleCall模式详解
SingleCall模式的主要特点是每次客户端调用远程对象方法时,Remoting都会为这次调用创建一个新的远程对象实例。这种模式的对象实例是无状态的,其生命周期由垃圾回收器(GC)管理。这种模式的优点在于,由于每次调用都创建新的实例,因此不存在并发访问的问题。这也意味着无法在不同的客户端调用之间保持状态信息。
三、客户端激活模式的特点
与SingleCall模式不同,客户端激活模式为每个客户端创建一个持久的远程对象实例。这意味着这些对象实例是有状态的,可以保存和恢复状态信息。这种模式在需要保持状态信息的应用场景中非常有用。客户端激活模式的对象实例生命周期可以自定义,更加灵活。由于多个客户端可能同时访问同一个对象实例,因此需要处理并发访问的问题。
四、两种模式的区别与实现
SingleCall模式和客户端激活模式在服务器端和客户端的实现方法有所不同。在服务器端,两种模式都需要实现远程对象的定义和规范。而在客户端,SingleCall模式通过GetObject()方法激活对象,而客户端激活模式则通过CreateInstance()方法激活对象。由于客户端激活模式需要处理有状态的对象,因此在处理并发访问时需要额外的机制来确保数据的安全性和一致性。
五、远程对象的定义与序列化
在Remoting中,远程对象的定义必须遵循一定的规范。远程对象类必须继承自MarshalByRefObject类,这是为了能够通过代理交换消息来跨越应用程序域边界进行通信。如果远程对象需要调用或传递其他对象(如类或结构),这些对象也必须实现序列化。在C中,可以通过在类定义上添加[Serializable]属性来实现对象的序列化。
六、总结与展望
本文详细了SingleCall模式和客户端激活模式在Remoting中的特性,以及远程对象的定义和序列化。在实际应用中,需要根据具体的需求和场景选择合适的模式。在未来的文章中,我们将继续Remoting中的其他特性,如事件的处理、安全机制等。敬请期待本系列之三的文章。服务器端实现细节
随着技术的不断进步,远程过程调用(Remoting)已成为实现分布式系统的重要技术之一。在服务器端,根据激活模式的不同,通道类型的不同,实现方式也有所不同。本文将深入服务器端的实现细节,以TcpChannel为例,详细阐述注册通道、注册远程对象及注销通道的整个过程。
一、注册通道
要实现跨应用程序域的通信,首先得注册通道。在Remoting中,提供了IChannel接口,其中包含TcpChannel和HttpChannel两种类型。以TcpChannel为例,注册步骤如下:
1. 在项目中添加“System.Runtime.Remoting”的引用。
2. 使用TcpChannel的命名空间“System.Runtime.Remoting.Channel.Tcp”。
3. 创建TcpChannel对象,将端口号作为参数传递。
4. 调用ChannelServices.RegisterChannel()方法注册该通道对象。
二、注册远程对象
注册了通道后,需要激活远程对象,必须在通道中注册该对象。根据激活模式的不同,注册对象的方法也有所不同。
1. SingleTon模式:
对于WellKnown对象,通过RemotingConfiguration.RegisterWellKnownServiceType()方法实现。需要提供远程对象的类型、对象的URI和激活模式(SingleTon)。
2. SingleCall模式:
注册对象的方法与SingleTon模式相似,只需将激活模式改为SingleCall。
3. 客户端激活模式:
先设置ApplicationName属性,然后通过RemotingConfiguration.RegisterActivatedServiceType()方法注册远程对象的类型。这里的ApplicationName实际上就是该对象的URI。
三、注销通道
若要关闭Remoting的服务,需注销已注册的通道。当我们注册通道时,会自动开启通道的监听。若关闭对通道的监听,则该通道无法接受客户端的请求。但通道仍然存在,若再次尝试注册该通道,会抛出异常。在关闭服务时,务必先注销通道,再关闭监听。
总结,服务器端实现Remoting通信的关键在于正确注册通道和远程对象,并根据激活模式选择合适的注册方法。在关闭服务时,要记得注销已注册的通道,以避免不必要的错误和异常。通过以上步骤,我们可以轻松实现服务器端的Remoting通信,为分布式系统提供强有力的支持。在编程的世界里,我们时常需要处理各种通道,以便在不同的程序或服务间传递信息。今天,让我们深入一下其中的一种场景——注册和关闭通道的操作。这些操作通常在分布式应用程序的上下文中进行,特别是在使用远程方法调用(Remoting)技术时。
我们需要获取当前已注册的通道列表。通过访问`ChannelServices.RegisteredChannels`属性,我们可以获取到一个通道的数组。这个数组包含了所有当前已经注册的通道实例。
接下来,我们的任务是关闭一个特定的通道。假设我们要关闭名为“MyTcp”的通道。我们遍历已注册的通道列表,检查每个通道的名称,如果名称匹配,则进行相应的操作。在这个过程中,我们将通道转型为`TcpChannel`类型,然后调用其`SListening`方法关闭监听,最后通过`ChannelServices.UnregisterChannel`方法注销该通道。
现在让我们转向客户端的部分。在客户端,主要的操作包括注册通道和获取远程对象。我们需要创建一个新的`TcpChannel`实例,并通过`ChannelServices.RegisterChannel`方法将其注册。值得注意的是,在实例化通道时并未指定端口号,这些信息被放在了URI中。
接下来是获取远程对象的操作。这里以WellKnown激活模式为例。在这种模式下,客户端通过`Activator.GetObject`方法获得服务器端的远程对象。这个方法需要两个参数:远程对象的类型和服务器的URI。通过这个URI,客户端能够定位到服务器上的服务,并获取相应的远程对象。如果是客户端激活模式,情况会有所不同。在这种模式下,客户端可以调用自定义的构造函数来创建远程对象。还可以使用`RemotingConfiguration.RegisterActivatedClientType`方法注册远程对象,或使用`Activator.CreateInstance`方法创建对象实例。
注册和关闭通道是分布式编程中的基础操作,它们允许我们在不同的程序或服务间建立联系,实现信息的传递。而客户端和服务器端的操作则涉及到如何正确地使用这些通道,以及如何通过这些通道获取或提供远程服务。这些操作对于理解和使用基于Remoting的分布式应用程序至关重要。与解读Remoting技术中的CreateInstance方法
在Remoting技术中,CreateInstance方法扮演着重要的角色。与GetObject方法不同,CreateInstance方法涉及到客户端对特定类型的实例的创建。而GetObject主要是用于获取已存在的对象,对象的创建通常在服务器端完成。CreateInstance方法具有多个重载版本,这里我们重点解读其中两个常用的方法。
第一个常用重载是:
```csharp
public static object CreateInstance(Type type, object[] args, object[] activationAttributes);
```
此方法允许你创建一个指定类型的对象实例,同时可以通过args参数传递构造函数的参数。这对于需要在客户端创建具有特定构造函数的实例时非常有用。其中:
type参数:指定要创建的对象的类型。
args参数:一个对象数组,用于传递构造函数的参数。如果此数组为空或未指定(在Visual Basic中为Nothing),则会调用不带任何参数的默认构造函数。
activationAttributes参数:包含可参与激活的一个或多个属性的数组。在某些情况下,这个参数可能被用于传递服务器的URL。
假设我们有一个远程对象类ServerObject,它具有接受三个参数的构造函数:
```csharp
ServerObject(string pName, string pSex, int pAge)
{
name = pName;
sex = pSex;
age = pAge;
}
```
你可以在客户端使用CreateInstance方法创建此类的新实例,并传递适当的参数。例如:
```csharp
object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};
object[] objs = {"wayfarer", "male", 28}; // 这是我们的构造函数的参数
ServerRemoteObject.ServerObject = Activator.CreateInstance(typeof(ServerRemoteObject.ServerObject), objs, attrs);
```
第二个常用重载是:
```csharp
public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);
```
此方法允许你在指定的程序集中查找并创建具有指定类型的对象实例。其中:
assemblyName参数:包含要查找的类型的程序集的名称。如果此参数为空(在Visual Basic中为Nothing),则搜索正在执行的程序集。
typeName参数:要创建的类型的名称。
activationAttributes参数:与前面相同,包含一个或多个可参与激活的属性的数组。此方法返回的是ObjectHandle类型,你可以通过其Unwrap方法来获取创建的实例。例如:
```csharp
object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};
ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject", "ServerRemoteObject.ServerObject", attrs);
ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();
```
在实际开发中,根据需要选择合适的CreateInstance重载版本,可以更好地利用Remoting技术实现远程对象的创建和交互。为了更好地使用UrlAttribute等属性,需要确保在代码中正确引入相应的命名空间。在 Remoting 技术中,创建和管理多个通道是一个重要的功能。通道作为不同端口间的通信桥梁,每个通道都需要一个独特的标识符,即通道名称。虽然 `IChannel` 接口提供了 `ChannelName` 属性,但这个属性是只读的,不能满足我们注册多个通道时命名的需求。为了解决这个问题,我们必须借助 `System.Collections` 命名空间中的 `IDictionary` 接口。
注册Tcp通道
我们首先创建一个 `IDictionary` 对象 `tcpProp`,并为其添加 "name" 和 "port" 两个键值对,分别表示通道的名称和端口号。接着,我们实例化一个 `TcpChannel` 对象,将 `tcpProp` 以及其他相关参数传递给它。通过 `ChannelServices.RegisterChannel(channel)` 注册这个通道。
示例代码如下:
```csharp
IDictionary tcpProp = new Hashtable();
tcpProp["name"] = "tcp9090";
tcpProp["port"] = 9090;
IChannel channel = new TcpChannel(tcpProp, new BinaryClientFormatterSinkProvider(), new BinaryServerFormatterSinkProvider());
ChannelServices.RegisterChannel(channel);
```
注册Http通道的操作与Tcp通道类似,只需更改通道的名称和端口号。
在远程对象的使用中,由于其元数据在客户端和服务器端都有涉及,为了保证代码的安全性和降低客户端对远程对象元数据的依赖,我们需要对传统的做法进行改进。即在服务器端实现远程对象,而在客户端则移除这些实现的元数据。由于激活模式的不同,客户端创建对象的方法也有所不同,因此分离元数据的相关性需要根据具体情况来处理。
WellKnown激活模式
在服务器端,我们提供远程对象的接口和具体类的实现。而在客户端,仅提供接口。这样做的好处是,即使客户端知道接口的定义,也无法直接实例化对象,因为它没有相关的类实现元数据。通过这种方式,我们可以确保代码的安全性。
示例中的 `IServerObject` 接口定义了远程对象的方法,而 `ServerObject` 类实现了这个接口。值得注意的是,两端生成的对象程序集名字必须相同,严格来说,是命名空间的名字必须保持一致。
客户端激活模式
对于客户端激活模式,无论是使用静态方法还是 `CreateInstance()` 方法,都必须在客户端调用构造函数来实例化对象。在客户端提供的远程对象不能只有接口而没有类的实现。这样确保了客户端能够正确地创建并激活远程对象。
通过这种方式,我们可以更加灵活地管理多个通道,并确保远程对象的安全性和独立性。这在分布式系统的开发中是非常重要的。实现远程对象与元数据的分离可以通过两种策略来实现,既保持了原有功能,又增强了系统的灵活性和扩展性。
方法一:利用WellKnown激活模式模拟客户端激活模式
在服务器端,我们采用抽象工厂的设计模式来实现远程对象的创建和管理。首先定义了两个接口:`IServerObject`和`IServerObjFactory`。其中,`IServerObject`接口定义了获取人员信息的操作,而`IServerObjFactory`接口则用于创建远程对象的实例。具体的实现类`ServerObject`继承了`MarshalByRefObject`,实现了这两个接口的方法。
在客户端,我们同样提供了这两个接口的实现。值得注意的是,我们在服务器端使用WellKnown激活模式注册的不是具体的远程对象,而是工厂对象`ServerObjFactory`。这样,在客户端激活时,实际上激活的是工厂对象而非远程对象本身。客户端通过工厂对象的`CreateInstance()`方法来创建远程对象实例,这种方式模拟了客户端激活模式。
方法二:利用替代类来取代远程对象的元数据
这种方法的核心思想是在客户端创建一个替代类,这个替代类实现了与远程对象相同的接口,但实际上并不包含真正的业务逻辑。它的作用是在客户端模拟远程对象的实例化过程。由于具体的业务逻辑都在服务器端实现,客户端只需要负责创建这个替代类并传递必要的参数即可。这种方式的实现避免了在客户端直接处理复杂的业务逻辑,使得系统更加灵活和易于维护。
通过这种替代类的设计,我们可以欺骗Remoting系统,使其在客户端认为正在处理的是真实的远程对象,但实际上只是处理了一个空壳或者模拟对象。真正的业务逻辑和数据都在服务器端处理,保证了系统的安全性和稳定性。这种设计也提高了系统的可扩展性和可维护性,使得系统的开发更加灵活和方便。
遥程对象中的方法与实现策略
在遥程对象交互中,服务器端负责提供方法的实现,而客户端需要提供相应的接口。这种交互中的核心在于方法的实现和调用机制。一个关键点是确保客户端类对象具备特定的方法。接下来,我们来通过代码演示这种机制。
看服务器端是如何操作的:
服务器端的类定义如下:它是一个继承了MarshalByRefObject的类,具有构造函数和获取人员信息的GetPersonInfo方法。这个方法的实现非常简单,它只是创建了一个Person对象并返回。但这只是示例,实际的实现可能会更复杂。
```csharp
public class ServerObject : MarshalByRefObject
{
public ServerObject() { } // 默认构造函数,具体实现在其他地方
public Person GetPersonInfo(string name, string sex, int age)
{
Person person = new Person(); // 创建Person对象实例
person.Name = name; // 设置Person对象的属性
person.Sex = sex;
person.Age = age;
return person; // 返回Person对象实例给客户端
}
}
```
在Microsoft的.NET Remoting的世界里,我们面临着如何处理和传送远程对象的挑战。如果一个远程对象孤单地传送过来,那还好办,我们只需关闭通道就可以了。但如果我们要传送的远程对象如繁星点点,又该如何去关闭指定的那颗星星呢?再次启动又是怎样的流程呢?答案就藏在Remoting的Marshal()和Disconnect()方法中。
我们来谈谈Marshal()方法。它像是一个魔术师,能将我们的MarshalByRefObject类的对象神奇地转化为ObjRef类的对象。这个转化是非常重要的,因为ObjRef对象包含了与远程对象通讯所需的所有关键信息。这样,我们可以将实例对象序列化,跨应用程序域、穿越网络进行传输。而客户端收到这些信息后,就可以调用远程对象了。
那么,当我们想要关闭某个特定的远程对象时,Disconnect()方法就派上用场了。这个方法能够断开指定的实例对象与通道的连接。要注意的是,只有之前实例化的对象才能被注销。我们可以根据需要创建特定的远程对象,然后在需要的时候断开连接。
在客户端调用远程对象方面,方法和之前WellKnown模式的调用方式类似,仍然是通过Activator.GetObject()来获取远程对象的引用。不过在实际操作中,我们会发现一种有趣的现象:由于服务器端显式实例化了远程对象,无论客户端有多少,它们调用的都是同一个远程对象。我们可以称这种模式为模拟的SingleTon模式。
再进一步,我们还可以利用Marshal()和Disconnect()方法来模拟客户端激活模式。我们可以创建一个工厂类,这个工厂类负责创建远程对象的实例。然后我们将这个工厂类的实例进行序列化并传输到客户端。客户端获取工厂类的实例后,就可以调用CreateInstance()方法来创建具体的远程对象实例了。这样对于多个客户端来说,它们使用的是同一个工厂类实例来创建各自的远程对象实例。当我们想要启动或关闭某个特定的远程对象时,只需要断开工厂类实例的连接就可以了。
Microsoft的.NET Remoting是一个博大精深的技术领域。这篇小文只是对其基础内容的介绍和解读,希望能够对大家有所帮助和启发。学习Remoting的过程如同攀登一座高峰,需要我们持之以恒、不断进取。或许只有通过不断的努力和实践,我们才能真正掌握这门技术,领略到那灯火阑珊处的精彩世界。也希望大家能够支持狼蚁SEO的分享和学习。
编程语言
- Microsoft .Net Remoting系列教程之一-.Net Remoting基础篇
- Vue.js上传图片到阿里云OSS存储的方法示例
- 用VB生成DLL封装ASP连接数据库的代码
- 解析php常用image图像函数集
- Vue.js路由vue-router使用方法详解
- babel基本使用详解
- 基于Vue实现图片在指定区域内移动的思路详解
- jQuery实现的网页左侧在线客服效果代码
- PHP判断IP并转跳到相应城市分站的方法
- PHP小偷程序的设计与实现方法详解
- PhpStorm的使用教程(本地运行PHP+远程开发+快捷键
- php正则修正符用法实例详解
- JavaScript图片轮播代码分享
- PHP的PDO常用类库实例分析
- Bootstrap嵌入jqGrid,使你的table牛逼起来
- PHP对象、模式与实践之高级特性分析