Remoting
分布式应用程序
.NET Remoting
可以用于访问另一个应用域中的对象,其体系结构额主要元素:
远程对象:指运行在服务器上的对象,客户机不能直接调用远程对象上的方法,但是可以根据代理来调用。
通道:用于客户机和服务器之间的通信。有
TCP
和
HTTP
两种通道协议。
消息:是为客户机和服务器之间的通信而创建的,消息被发送到通道中,消息中包含的内容:远程对象的信息、被调用的方法名称及所有参数。
格式标识符:用于定义消息是如何传送到通道中的。
格式标识符提供者:用于把格式标识符与通道连接起来。
代理对象:客户机调用的是代理对象上的方法,而不是远程对象上的方法,代理对象包括两种:透明代理对象和真实代理对象。
消息接收器:是一个截取器对象,在服务器和客户机上都有这样的对象,接收器与通道相联系,真实代理对象使用消息接收器把消息传送到通道中,因此在消息进入通道之前,接收器可以进行截取工作。
激活器:客户机可以通过激活器在服务器上创建远程对象,或截取一个被激活的服务器对象的代理对象。
RemotingConfiguration
类:用于配置远程服务器和客户机的实用类。
ChannelServices
类:是一个实用类,可用于注册并把消息传送到通道中。
见如下简单例子:
远程对象:
远程对象类继承于
MarshalByRefObject
,
并且定义了远程的实现方法,形成
Remoting
的装配件
Remoting.dll
,当服务器和客户机程序调用远程对象时需要引用装配件
Remoting.dll.
namespace
Remoting
{
public
class
HelloServer:MarshalByRefObject
{
public HelloServer()
{
System.Console.WriteLine("HelloServer activated");
}
public
String HelloMethod(String name)
{
Console.WriteLine(
"Server Hello.HelloMethod : {0}", name);
return
"Hi there " + name;
}
}
}
服务器:必须引用Remoting.dll的装配件,服务器上需要创建一个含有端口号的ServerChannel,这样远程对象就可以使用这个服务器通道了。WellKnownObjectMode.Singleton模式说明为每一个方法调用都创建新的实例,服务器不保存远程对象中的状态。
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
using
System.Runtime.Remoting.Channels.Http;
using
Remoting;
namespace
Server
{
class
Program
{
static
int
Main(string[] args)
{
TcpChannel channel1 = newTcpChannel(8085);
HttpChannel channel2 = newHttpChannel(8086);
ChannelServices.RegisterChannel(channel1, false);
ChannelServices.RegisterChannel(channel2, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(HelloServer), "SayHello", WellKnownObjectMode.Singleton);
System.Console.WriteLine("Enter Any Key,Exit");
System.Console.ReadLine();
return 0;
}
}
}
客户机:必须引用Remoting.dll的装配件,这里用到了反射原理,使得透明代理对象看起来象真实对象,实际是在反射机制下对取了真实对象的元数据。透明代理对象使用真实代理对象把消息发送给通道。
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Http;
using
System.Runtime.Remoting.Channels.Tcp;
using
Remoting;
namespace
Client
{
class
Program
{
static
void
Main(string[] args)
{
TcpChannel channel1 = newTcpChannel();
ChannelServices.RegisterChannel(channel1, false);
HelloServer obj1 = (HelloServer)Activator.GetObject(typeof(Remoting.HelloServer), "tcp://localhost:8085/SayHello");
if (obj1 == null)
{
System.Console.WriteLine("Could not locate TCP server");
}
HttpChannel channel2 = newHttpChannel();
ChannelServices.RegisterChannel(channel2, false);
HelloServer obj2 = (HelloServer)Activator.GetObject(typeof(Remoting.HelloServer), "http://localhost:8086/SayHello");
if (obj2 == null)
{
System.Console.WriteLine("Could not locate HTTP server");
}
Console.WriteLine("Client1 TCP HelloMethod {0}", obj1.HelloMethod("Caveman1"));
Console.WriteLine("Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
Console.ReadLine();
}
}
}