[Remoting专题系列] 九:动态发布
使用动态发布有什么好处?
1. 避开 SAO 只能使用默认构造方法的限制。
2. 自主管理 SAO 的载入、卸载,以及其 URI。
RemotingServices
通过使用类 RemotingServices 提供的方法,我们可以很轻松实现这些目标。
Marshal: 用于将 MarshalByRefObject 转换为 ObjRef 类的实例。
Connect:客户端可以用该方法创建远程代理对象的实例。
Disconnect:断开服务器远程对象与信道的连接。客户端代理在断开后调用任何方法都会触发 RemotingException。
Unmarshal:接受 ObjRef 并从它创建一个客户端代理对象。这个方法很少被使用,因为多数情况下我们并不会直接将 ObjRef 显示传递给客户端,而是交由 Remoting 基础结构来处理。
ObjRef
ObjRef 是远程对象的可序列化表示,用于跨应用程序域边界传输对象引用。为对象创建 ObjRef 称为封送。可以通过信道将 ObjRef 传输到另一个应用程序域(可能在另一个进程或计算机上)。达到其他应用程序域后,需立即分析 ObjRef,以便为该对象创建一个代理(通常连接到实际的对象)。此操作称为拆收处理 (Unmarshaling)。在拆收处理过程中,分析 ObjRef 以提取远程对象的方法信息,并创建透明代理和 RealProxy 对象。在透明代理注册到公共语言运行库之前,将已分析的 ObjRef 的内容添加到透明代理中。
ObjRef 包含:描述所封送对象的 Type 和类的信息,唯一标识特定对象实例的 URI,以及有关如何到达对象所在的远程处理分支的相关通信信息。
动态发布示例
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Services;
namespace Learn.Library.Remoting
{
/// <summary>
/// 远程类型
/// </summary>
public class Data : MarshalByRefObject
{
public void Test()
{
Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
}
public void Disconnect()
{
// 断开连接
RemotingServices.Disconnect(this);
}
}
public class RemotingTest2
{
/// <summary>
/// 服务器端代码
/// </summary>
static void Server()
{
AppDomain server = AppDomain.CreateDomain("server");
server.DoCallBack(delegate
{
TcpServerChannel channel = new TcpServerChannel(801);
ChannelServices.RegisterChannel(channel, false);
// 创建远程对象实例,当然也可以使用非默认构造方法。
// 此方式类似于 SAO.Singleton 。
Data data = new Data();
// 封送远程对象。
ObjRef objRef = RemotingServices.Marshal(data, "data");
});
}
/// <summary>
/// 客户端代码
/// </summary>
static void Client()
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
// 连接服务器,并创建代理实例。
Data data = (Data)RemotingServices.Connect(typeof(Data), "tcp://localhost:801/data");
// 调用远程对象方法。
data.Test();
// 调用远程对象方法,断开连接。
data.Disconnect();
// 再次调用远程对象方法时,因连接已断开,将抛出 RemotingException。
data.Test();
}
static void Main()
{
Server();
Client();
}
}
}
1. 避开 SAO 只能使用默认构造方法的限制。
2. 自主管理 SAO 的载入、卸载,以及其 URI。
RemotingServices
通过使用类 RemotingServices 提供的方法,我们可以很轻松实现这些目标。
Marshal: 用于将 MarshalByRefObject 转换为 ObjRef 类的实例。
Connect:客户端可以用该方法创建远程代理对象的实例。
Disconnect:断开服务器远程对象与信道的连接。客户端代理在断开后调用任何方法都会触发 RemotingException。
Unmarshal:接受 ObjRef 并从它创建一个客户端代理对象。这个方法很少被使用,因为多数情况下我们并不会直接将 ObjRef 显示传递给客户端,而是交由 Remoting 基础结构来处理。
ObjRef
ObjRef 是远程对象的可序列化表示,用于跨应用程序域边界传输对象引用。为对象创建 ObjRef 称为封送。可以通过信道将 ObjRef 传输到另一个应用程序域(可能在另一个进程或计算机上)。达到其他应用程序域后,需立即分析 ObjRef,以便为该对象创建一个代理(通常连接到实际的对象)。此操作称为拆收处理 (Unmarshaling)。在拆收处理过程中,分析 ObjRef 以提取远程对象的方法信息,并创建透明代理和 RealProxy 对象。在透明代理注册到公共语言运行库之前,将已分析的 ObjRef 的内容添加到透明代理中。
ObjRef 包含:描述所封送对象的 Type 和类的信息,唯一标识特定对象实例的 URI,以及有关如何到达对象所在的远程处理分支的相关通信信息。
动态发布示例
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Services;
namespace Learn.Library.Remoting
{
/// <summary>
/// 远程类型
/// </summary>
public class Data : MarshalByRefObject
{
public void Test()
{
Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
}
public void Disconnect()
{
// 断开连接
RemotingServices.Disconnect(this);
}
}
public class RemotingTest2
{
/// <summary>
/// 服务器端代码
/// </summary>
static void Server()
{
AppDomain server = AppDomain.CreateDomain("server");
server.DoCallBack(delegate
{
TcpServerChannel channel = new TcpServerChannel(801);
ChannelServices.RegisterChannel(channel, false);
// 创建远程对象实例,当然也可以使用非默认构造方法。
// 此方式类似于 SAO.Singleton 。
Data data = new Data();
// 封送远程对象。
ObjRef objRef = RemotingServices.Marshal(data, "data");
});
}
/// <summary>
/// 客户端代码
/// </summary>
static void Client()
{
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
// 连接服务器,并创建代理实例。
Data data = (Data)RemotingServices.Connect(typeof(Data), "tcp://localhost:801/data");
// 调用远程对象方法。
data.Test();
// 调用远程对象方法,断开连接。
data.Disconnect();
// 再次调用远程对象方法时,因连接已断开,将抛出 RemotingException。
data.Test();
}
static void Main()
{
Server();
Client();
}
}
}