Remoting编程知识一

编程

Remoting基础

基本原理
当客户端创建远程RemotableClass的一个实例,.NET框架在客户端应用程序域中产生一个代理。该代理看起来就像实际对象。代理收到调用后,通过通道连接到远程的对象。

一、编写步骤

第一步

编写一个DLL,其中包含所要Remottable的类

public class RemotableClass:MarshalByRefObject

{

….

}

第二步

服务器进程注册该remotable 类以便其他应用程序可以激活。根据该对象是如何激活,服务器通过两种静态方法来注册:RegisterActivatedServiceType或者RegisterWellKnownServiceType。下面的语句使用RegisterWellKnownServiceType来注册RemotableClass,以便远程激活。

RemotingConfiguration.RegisterWellKnownServiceType(

Typeof(RemotableClass), //Remotable类

“RemoteObject”, // Remotable类的URI

WellKnownObjectMode.SingleCall); //激活模式

第一个参数是指能远程化的类。

第二个是指客户端使用来激活对象的URI----也就是客户端告诉服务器来激活

RemotableClass实例的URI。

第三个参数指定激活模式。有两种选择。WellKnownObjectMode.SingleCall是指为客户端的每一次调用创建一个新的实例。WellKnownObjectMode.Singleton是指创建一个RemotableClass实例来处理所有客户端的调用。

第三步

为了使客户端可以使用RemotableClass,服务器进程必须创建,注册一个通道。该通道提供对象和远程客户端交流的一个渠道。在服务器端,.NET框架提供了两种通道:

System.Runtime.Remoting.Channels.Tcp.TcpServerChannel:可以接受远程客户端的TCP连接。

System.Runtime.Remoting.Channels.Http.HttpServerChannel:接受HTTP连接。

下面的语句创建一个在1234端口监听的TcpServerChannel通道,并用.NET框架注册:

TcpServerChannel channel = new TcpServerChannel(1234);

ChannelServices.RegisterChannel(channel);

下面的语句注册了一个在1234端口监听的HTTP通道:

HttpServiceChannel channel = new HttpServerChannel(1234);

ChannelServices.RegisterChannel(channel);

TcpServerChannel更有效率一点。HttpServerChannel是使用IIS作为远程激活代理时使用的选择。

第四步

在客户端要想创建远程类的一个实例,也必须做一些注册。

第一必须注册一个客户端通道。.NET框架提供了两种类型的客户端通道:TcpClientChannel和HttpClientChannel,分别和服务器端通道相对应。

第二,如果客户端想使用new操作符来生产远程对象,必须将远程对象注册到本地应用程序域。

RemotingConfiguration.RegisterWellKnownClientType是在客户端注册一个类。

RemotingConfiguration.RegisterWellKnownServiceType是在服务器上注册一个类。

下面的代码在客户端注册了一个TCP通道,而且也将RemotableClass注册到本地应用程序域中:

TcpClientChannel channel = new TcpClientChannel();

ChannelServices.RegisterChannel(channel);

RemotingConfiguration.RegisterWellKnownClientType(

Typeof(RemotableClass),

“tcp://localhost:1234/RemoteObject”);

第二个参数是指远程对象的URL。

协议必须匹配应用程序注册的通道协议。

可以使用机器名或者IP地址来替换localhost。

端口数必须好服务器端监听的端口数一样。

对象URI,必须和服务器用RegisterWellKnownServiceType注册的匹配。

第五步

在客户端使用new来产生代理:

RemotableClass rc = new RemotableClass();

这个操作在客户端应用程序域中产生一个代理,返回RemotableClass的一个引用。

二、实际范例

ClockServer.cs

using System;
public class Clock : MarshalByRefObject
{
public string GetCurrentTime ()
{
return DateTime.Now.ToLongTimeString ();
}
}
TimeServer.cs

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class MyApp
{
static void Main ()
{
TcpServerChannel channel = new TcpServerChannel (1234);
ChannelServices.RegisterChannel (channel);

RemotingConfiguration.RegisterWellKnownServiceType
(typeof (Clock), "Clock", WellKnownObjectMode.SingleCall);

Console.WriteLine ("Press Enter to terminate...");
Console.ReadLine ();
}
}
TimeClient.cs

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class MyApp
{
static void Main ()
{
TcpClientChannel channel = new TcpClientChannel ();
ChannelServices.RegisterChannel (channel);

RemotingConfiguration.RegisterWellKnownClientType
(typeof (Clock), "tcp://localhost:1234/Clock");
Clock clock = new Clock ();
Console.WriteLine (clock.GetCurrentTime ());
}
}
编译:

1. csc /t:library clockserver.cs
2. csc /r:clockserver.dll timeserver.cs
3. csc /r:clockserver.dll timeclient.cs
要将ClockServer.dll拷贝到客户端。因为创建远程对象的代理时,.NET框架需要描述Clock类的原数据。它可以从DLL中得到原数据。

三、配置方式

TimeServer和TimeClient在其源代码内部注册通道和远程化的类。这样有个缺点,一旦任何一个注册数据改变,你必须要修改源代码,并重新编译。

这就是为什么.NET框架支持另一种形式的注册。声明注册是通过调用静态

RemotingConfiguration.Configure方法来从Config文件中得到信息。

范例如下:

ClockServer.cs

using System;

public class Clock : MarshalByRefObject
{
public string GetCurrentTime ()
{
return DateTime.Now.ToLongTimeString ();
}
}

TimeServer.cs

using System;
using System.Runtime.Remoting;

class MyApp
{
static void Main ()
{
RemotingConfiguration.Configure ("TimeServer.exe.config");
Console.WriteLine ("Press Enter to terminate...");
Console.ReadLine ();
}
}
TimeServer.exe.config

<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="SingleCall" type="Clock, ClockServer"
objectUri="Clock" />
</service>
<channels>
<channel ref="tcp server" port="1234" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
TimeClient.cs

using System;
using System.Runtime.Remoting;

class MyApp
{
static void Main ()
{
RemotingConfiguration.Configure ("TimeClient.exe.config");
Clock clock = new Clock ();
Console.WriteLine (clock.GetCurrentTime ());
}
}
TimeClient.exe.config

<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown type="Clock, ClockServer"
url="tcp://localhost:1234/Clock" />
</client>
<channels>
<channel ref="tcp client" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
该方式的缺点是配置文件可以被修改和删除。

四、激活方式

.NET框架将可远程化对象分为两种:服务器激活对象和客户端激活对象。服务器端激活对象是通过RemotingConfiguration’sRegisterWellKnownServiceType和

RegisterWellKnownClientType方法注册的。上面的范例都是服务器端激活对象。客户端激活对象是通过RegisterActivateServiceType和RegisterActivatedClientType注册的。

服务器端激活对象被称为服务器激活的,因为当客户端使用new,只有一个代理被创建。实际对象知道通过代理来调用一个方法时才被创建(激活)。换句话说,不是客户端决定什么时候去创建物理上的真正对象。客户端激活对象在客户端使用new时就在服务器上创建。这个是第一个差别。

第二个差别是客户端激活对象可以使用非缺省构造函数(带参数的构造函数)激活。服务器端机会对象不支持非缺省构造函数,因为使用new只是创建一个代理,并没有创建对应的实际对象。客户端激活对象可以通过new同时创建代理和对象。

第三个差别是客户端和对象是如何联系在一起的。当注册服务器激活对象时,你可以指定激活模式来决定为每一个请求创建一个对象实例还是创建一个对象实例来服务所有的请求。这两中激活模式是:

WellKnownObjectMode.SingleCall:为每个请求创建一个唯一的对象实例。

WellKonwnObjectMode.Singleton:创建一个对象实例来服务所有的请求

通常根据环境来选择合适的激活模式。举例来说,如果一个远程化对象提供了一个”One-shot”服务,不需要在多次调用间保持状态或者不需要在所有客户端同享状态,那么SingleCall是个正确的选择。因为每一次的请求产生的是一个新的对象实例。如果想在客户端之间传递数据,则要使用Singleton。

Singleton对象一个值得注意的地方是线程的同步问题。当两个客户端同时调用该对象的方法时,可能会出现错误,这时要使用.NET框架提供的同步机制。

客户端激活对象提供第三种选择。当使用客户端激活对象时,该对象仅为此客户端服务,可以在多次调用间保持状态。

Single-call服务器激活对象,Singleton服务器激活对象和客户端激活对象的提供了三种不同的激活模式。当不需要在所有客户端共享状态时,则使用Single-call。当要在所有客户端共享状态时则使用Singleton。当不需要所有的客户端连接到同一个对象,只要保持该客户端自己的状态时,则使用客户端激活对象。

程序范例:

Stopwatch.cs

using System;
public class Stopwatch : MarshalByRefObject
{
DateTime mark = DateTime.Now;
public void Start ()
{
mark = DateTime.Now;
}
public int Stop ()
{
return (int) ((DateTime.Now - mark).TotalMilliseconds);
}
}
StopwatchServer.cs

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class MyApp
{
static void Main ()
{
TcpServerChannel channel = new TcpServerChannel (1234);
ChannelServices.RegisterChannel (channel);

RemotingConfiguration.RegisterActivatedServiceType
(typeof (Stopwatch));

Console.WriteLine ("Press Enter to terminate...");
Console.ReadLine ();
}
}
StopwatchClient.cs

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class MyApp
{
static void Main ()
{
TcpClientChannel channel = new TcpClientChannel ();
ChannelServices.RegisterChannel (channel);
RemotingConfiguration.RegisterActivatedClientType
(typeof (Stopwatch), "tcp://localhost:1234");
Stopwatch sw = new Stopwatch ();
sw.Start ();
Console.WriteLine ("Press Enter to show elapsed time...");
Console.ReadLine ();
Console.WriteLine (sw.Stop () + " millseconds");
}
}
五、Activator.GetObject和Activator.CreateInstance方法

new操作符并不是激活远程对象的唯一方法。.NET框架提供了其他的激活方法:GetObject和CreateInstance。它们都是System.Activator类的成员。GetObject被用来激活在服务器端激活的对象,而CreateInstance被用来激活在客户端激活的对象。

当使用GetObject或者CreateInstance来激活远程对象时,不再需要调用RegisterActivatedClientType或者RegisterWellKnownClientType来注册服务器上可远程化的类。例如:激活在服务器端激活的对象时:

RemotingConfiguration.RegisterWellKnownClientType(typeof(Clock),”tcp://localhost:1234/Clock”);

Clock clock = new Clock();

可以使用下面的方法代

Clock clock =(Clock) Activator.GetObject(typeof(Clock,”tcp://localhost:1234/Clock”);

激活客户端对象时:

RemotingConfiguration.RegisterActivatedClientType(typeof(Stopwatch),”tcp://localhost:1234”);

Stopwatch sw = new StopWatch();

可以这样的方式:

object[] url ={new UrlAttribute(“tcp://localhost:1234”)};

Stopwatch sw =(Stopwatch) Activator.CreateInstance(typeof(Stopwatch),null,url);

为什么要使用它们来代替new呢?因为在你仅知道URL和接口时,GetObject和CreateInstance可以仍使用。假设改变Clock类,它实现一个IClock接口。

使用GetObject时:

Iclock ic = (Iclock)Activator.GetObject(typeof(Iclock),”tcp://localhost:1234/Clock”);

如果使用new,则会出现编译错误,因为new不能接受一个接口名称:

RemotingConfiguration.RegisterWellKnownClientType
(typeof (IClock), "tcp://localhost:1234/Clock");
IClock ic = new IClock ();

六、对象生存期和租用期

一个single-call服务器端激活对象只在方法调用期间生存。之后,被垃圾回收器标记为删除。Singleton 服务器激活对象和客户端激活对象不一样,他们的生存期被租用控制。租用是一个对象,它实现了定义在System.Runtime.Remoting.Lifetime名称空间的Ilease接口。

Singleton 服务器端激活对象和客户端激活对象缺省的租用对象有一个5分钟的InitialLeaseTime,2分钟的RenewOnCallTime,5分钟的CurrentLeaseTime。如果对象没有方法被调用,当CurrentLeaseTime为0时它被清除,也就是5分钟后被清除。

时间: 2024-11-05 14:56:55

Remoting编程知识一的相关文章

Remoting编程知识二

编程 Remoting高级知识 一. 如何使用IIS作为激活代理 .NET Remoting和DCOM之间的一个区别是前者不支持自动运行的服务器进程.需要人工启动服务器进程来注册用来远程激活的类和监听请求.而对于DCOM,当远程客户端调用CoCreateInstanceEx或者其他激活API时,会自动运行服务器进程. .NET remoting 提供了两种方法来避免人工启动服务器.第一个是将服务器应用程序当做一个服务来实现.可以编写一个从 System.ServiceProcess.Servic

黄聪:SEO专家必须具备编程知识

黄聪认为:SEO专家必须具备编程知识.黄聪在学习SEO的时候,看到网络上流传着大量"零建站基础学习SEO,轻松月赚5000","不会建站怎么办?教你SEO赚钱月赚1万"等等广告.其实,懂得网赚并不等于懂得SEO. 懂得网赚不等于懂得SEO 相信很多自称SEO专家的人都不懂得编程,但是的确不妨碍他们将某些难度较大的词做上百度首页,因为他们有足够多的内容和外链,而有这些对于做一般的关键词已经足够了.但是他们真的懂得搜索引擎吗?要知道他们自称的是SEO专家而不是网赚专家,

java-初学编程知识,望各位帮忙解决

问题描述 初学编程知识,望各位帮忙解决 最近在学习Java ,如何让myeclipse用数据库中的数据??如何将数据库和myeclipse连接起来? 解决方案 import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Connection; import java.sql.Statement; public class MysqlDemo { pu

.NET Remoting编程简介(转)

.NET Remoting编程简介 (刘彦青编译 2001年11月02日 09:25) .NET Remoting提供了一个功能强大.高效的处理远程对象的方法,从结构上而言,.NET Remote对象非常适合通过网络访问资源,而又无需处理由基于SOAP的WebServices所带来的难题..NET Remoting使用起来比Java的RMI简单,但要比创建Web Service难度大一些.广告

程序员编程知识经验总结

感觉听上去也算合情合理.毕竟,新的编程语言和技术在源源不断地面世.但是我要告诉你,编程语言比很多人想得都要"长寿". 语法不是难点 对于 Java 程序员,学习 Python 就像说英语的去学习法语.当然这两者是毫无关联的.但是相同的是,都需要学习新的语法.语法只是表面上的不同,所有的核心概念都是相通的. 无论你换哪种编程语言去写程序,我们都可以借鉴其相似的类型.数据结构和逻辑等基础知识.如果你已经学过布尔值.整数.浮点数和字符串,那么一般情况下它们在新语言中的用法也是相同的.其他如列

.NET Remoting编程简介

编程 .NET Remoting提供了一个功能强大.高效的处理远程对象的方法,从结构上而言,.NET Remote对象非常适合通过网络访问资源,而又无需处理由基于SOAP的WebServices所带来的难题..NET Remoting使用起来比Java的RMI简单,但要比创建Web Service难度大一些. 在本篇文章中,我们将创建一个从数据库读入内容的远程对象.文中还包括了一个忽略数据库功能的替补对象,以使没有数据库可以使用的读者仍然能够使用.NET Remoting. 第一步:创建共享库

Asp.Net异步编程知识

写在前面的话,很久没有写Blog了,不对,其实一致就没有怎么写过.今天有空,我也来写一篇Blog 随着.Net4.5的推出,一种新的编程方式简化了异步编程,在网上时不时的也看到各种打着Asp.Net异步编程的口号,如何提高性能,如何提高吞吐率! 好多文章都说得不清楚,甚至是错误的.只看到了一些表现,混淆概念.希望这篇文章能够能够对一部分人理解Asp.net异步编程模型. 1基础知识,谈一个初学者不容易理解的基础知识,这个基础知识,很不基础的哦 先看这个代码 ThreadPool.GetMaxTh

c语言基础编程知识:switch开关语句浅析

在c语言的选择结构中,if--else语句一般指用来处理一个或者两个分支的选择结构,如果分支较多还使用if_else语句的话就会导致程序运行效率降低,代码可读性减弱.所以,switch就应运而生了.switch的英文意思是"切换",所以它在编程中就做了一个选择分支的专业术语. 首先我们来交流下switch语句的基本语法 switch (表达式) //计算表达式的值 { case 常量 1: //如果等于常量1 语句; //case后面只能加常量 break; //跳出分支,执行swit

javascript中常用编程知识_基础知识

1.null 与 undefined * 从一个对象中获取某个属性,如果该对象及其 prototype 链 中的对象都没有该属性的时候,该属性的值为 undefined . * 一个 function 如果没有显式的通过 return 来返回值给其调用者的话,其返回值就是 undefined .有一个特例就是在使用new的时候. * JavaScript 中的 function 可以声明任意个形式参数,当该 function 实际被调用的时候,传入的参数的个数如果小于声明的形式参数,那么多余的形