Remoting专题2(客户端和服务端之间的通信)

1   服务器端
根据第一部分所述,根据激活模式的不同,通道类型的不同服务器端的实现方式也有所不同。大体上说,服务器端应分为三步:
1)注册通道
       要跨越应用程序域进行通信,必须实现通道。如前所述,Remoting 提供了 IChannel 接口,分别包含 TcpChannel 和 HttpChannel 两种类型的通道。这两种类型除了性能和序列化数据的格式不同外,实现的方式完全一致,因此下面我们就以 TcpChannel 为例。
      注册 TcpChannel,首先要在项目中添加引用“System.Runtime.Remoting”,然后 using名字空间:System.Runtime.Remoting.Channel.Tcp。代码如下:
    
  
       TcpChannel channel = new TcpChannel(8080);
       ChannelServices.RegisterChannel(channel);
2)注册远程对象
注册了通道后,要能激活远程对象,必须在通道中注册该对象。根据激活模式的不同, 注册对象的方法也不同。
(1) SingleTon 模式 对于 WellKnown 对象,可以通过静态方法 RemotingConfiguration.RegisterWellKnownServiceType()来实现
RemotingConfiguration.RegisterWellKnownServiceType( 
 typeof(ServerRemoteObject.ServerObject), 
 "ServiceMessage",WellKnownObjectMode.SingleTon);
(2)SingleCall 模式
注册对象的方法基本上和 SingleTon 模式相同,只需要将枚举参数WellKnownObjectMode 改为 SingleCall 就可以了。
RemotingConfiguration.RegisterWellKnownServiceType( 
 typeof(ServerRemoteObject.ServerObject), 
 "ServiceMessage",WellKnownObjectMode.SingleCall);
(3)客户端激活模式
对于客户端激活模式,使用的方法又有不同,但区别不大,看了代码就一目了然。
RemotingConfiguration.ApplicationName = "ServiceMessage"; 
RemotingConfiguration.RegisterActivatedServiceType( 
 typeof(ServerRemoteObject.ServerObject));
       为什么要在注册对象方法前设置 ApplicationName 属性呢?其实这个属性就是该对象的URI。对于 WellKnown 模式,URI 是放在 RegisterWellKnownServiceType()方法的参数中,当然也可以拿出来专门对 ApplicationName 属性赋值。而 RegisterActivatedServiceType()方法的重载中,没有 ApplicationName 的参数,所以必须分开。
3)注销通道
如果要关闭 Remoting 的服务,则需要注销通道,也可以关闭对通道的监听。在 Remoting中当我们注册通道的时候,就自动开启了通道的监听。而如果关闭了对通道的监听,则该通道就无法接受客户端的请求,但通道仍然存在,如果你想再一次注册该通道,会抛出异常。
//获得当前已注册的通道; 
IChannel[] channels = ChannelServices.RegisteredChannels; 
//关闭指定名为 MyTcp 的通道; 
foreach (IChannel eachChannel in channels) 
{ 
 if (eachChannel.ChannelName == "MyTcp") 
 { 
 TcpChannel tcpChannel = (TcpChannel)eachChannel; 
 //关闭监听; 
 tcpChannel.StopListening(null); 
 //注销通道; 
 ChannelServices.UnregisterChannel(tcpChannel); 
 } 
}
2 客户端
客户端主要做两件事,一是注册通道。这一点从图一就可以看出,Remoting 中服务器端和客户端都必须通过通道来传递消息,以获得远程对象。第二步则是获得该远程对象。
1)注册通道:
 
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel);

  注意在客户端实例化通道时,是调用的默认构造函数,即没有传递端口号。事实上,这个端口号是缺一不可的,只不过它的指定被放在后面作为了 Uri 的一部分。

2)获得远程对象
与服务器端相同,不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是 WellKnown 激活模式和客户端激活模式之间的区别,而对于 SingleTon 和 SingleCall 模式,客户端的实现完全相同。
(1) WellKnown 激活模式
要获得服务器端的知名远程对象,可通过 Activator 进程的 GetObject()方法来获得:
ServerRemoteObject.ServerObject serverObj = 
(ServerRemoteObject.ServerObject)Activator.GetObject( 
 typeof(ServerRemoteObject.ServerObject), 
"tcp://localhost:8080/ServiceMessage");
首先以 WellKnown 模式激活,客户端获得对象的方法是使用 GetObject()。其中参数第一个是远程对象的类型。第二个参数就是服务器端的 uri。如果是 http 通道,自然是用http://localhost:8080/ServiceMessage 了。因为我是用本地机,所以这里是 localhost,你可以用具体的服务器 IP 地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名,即 ApplicationName 属性的内容。
(2) 客户端激活模式
如前所述,WellKnown 模式在客户端创建对象时,只能调用默认的构造函数,上面的代码就说明了这一点,因为 GetObject()方法不能传递构造函数的参数。而客户端激活模式则可以通过自定义的构造函数来创建远程对象。
客户端激活模式有两种方法:
1) 调用 RemotingConfiguration 的静态方法 RegisterActivatedClientType()。这个方法返回值为
Void,它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。
RemotingConfiguration.RegisterActivatedClientType(
typeof(ServerRemoteObject.ServerObject),
"tcp://localhost:8080/ServiceMessage");
ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();
2) 调用进程 Activator 的 CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的 GetObject()不同的是,它要在客户端调用构造函数,而 GetObject()只是获得对象,而创建实例是在服务器端完成的。CreateInstance()方法有很多个重载,我着重说一下其中常用的两个
a、 public static object CreateInstance(Type type, object[] args, object[] activationAttributes);
参数说明:
type:要创建的对象的类型。args :与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 args 为空数组或空引用(Visual Basic 中为 Nothing),则调用不带任何参数的构造函数(默认构造函数)。activationAttributes :包含一个或多个可以参与激活的属性的数组。
b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] 
activationAttribute)
参数说明:
assemblyName :将在其中查找名为 typeName 的类型的程序集的名称。如果 assemblyName为空引用(Visual Basic 中为 Nothing),则搜索正在执行的程序集。
typeName:首选类型的名称。
activationAttributes :包含一个或多个可以参与激活的属性的数组。

猜你喜欢

转载自www.cnblogs.com/123-com/p/12284735.html