.Net组件程序设计之远程调用(二)
.Net组件程序设计之远程调用(二)
激活模式
引用封送对象激活类型两种,
一种是客户端激活类型,一种是服务器端激活.
客户端激活对象
客户端激活方式:当客户端创建一个远程对象时,客户端得到的是一个新的实例引用,新的实例可以在内存中维持状态,并且可以使用参数化构造函数来激活远程对象。
服务器激活模式single-call
SingleCall激活方式:当客户端使用一个服务器激活方式为SingleCall的对象时,.NET为每个方法调用创建一个新对象,在方法执行完毕后,对象则被销毁,客户端虽然维持着对远程对象的引用,但是真实对象已经被销毁了。
服务器激活Singleton
Singleton激活方式:所有客户端共享一个远程对象。
下面为大家演示几段示例,就详细的清楚每一种激活方式的作用了。
服务端代码
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
namespace RemoteServer
/// <summary>
/// 服务端
/// </summary>
public class MyClass : MarshalByRefObject
{
public MyClass()
{
_count++;
string mes = AppDomain.CurrentDomain.FriendlyName;
Console.WriteLine(mes);
} private int _count = ; public event EventHandler NumberChanged; public void Count()
{
_count++;
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "_" + _count.ToString());
} public void OnNumberChanged(int num)
{
if (NumberChanged != null)
{
NumberChanged(num, null);
}
}
} public class EventMehtodClass : MarshalByRefObject
{
[OneWay]
public void OnNumberChanged(object sender, EventArgs e)
{
if (sender != null)
{
Console.WriteLine(sender.ToString());
}
}
}
2.编程式:
宿主服务端(服务器端)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services;
using RemoteServer; namespace RemoteServerHost #region 编程式 宿主服务端注册 信道和对象类型
Console.WriteLine("开始Tcp注册信道");
IChannel tcpChannel = new TcpChannel();
ChannelServices.RegisterChannel(tcpChannel, false);//注册Tcp类型信道
Console.WriteLine("Tcp信道注册完成————————————————");
Console.WriteLine("开始 服务器激活类型SingleCall模式的宿主服务器端类型注册");
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass",WellKnownObjectMode.SingleCall);
Console.WriteLine("类型注册完成");
#endregion Thread.Sleep(new TimeSpan(, , ));
Console.WriteLine("释放Tcp信道");
ChannelServices.UnregisterChannel(tcpChannel);
这里所用的激活方式是 服务器SingleCall激活方式,通过RemotingConfiguration.RegisterWellKnownServiceType()方法来注册类型,第二个参数为统一资源标识符(URI),很好理解就是字面的意思,远程对象就是资源,标识资源的一个符号(名称),有了它,客户端在调用远程对象的时候才知道具体在哪。因为是服务器激活方式所以URI是在包含在注册类型的方法中的,而如果是客户端激活类型注册的话,则使用RemotingConfiguration.RegisterActivatedServiceType(typeof(MyClass));
有的朋友会问了,这样统一资源标识符不是没设置吗?是的,确实没有设置,客户端激活类型注册的时候URI是这样设置
RemotingConfiguration.ApplicationName = "RWCTmyclass";
客户端(调用端)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services;
using RemoteServer; namespace RemoteClient #region 编程式本地注册
Thread.Sleep(new TimeSpan(, , ));//便于调,使当前客户端线程阻塞7秒,确保宿主服务端已经运行
string url = "tcp://localhost:8003/RWCTmyclass";
Console.WriteLine("开始客户端注册类型");
RemotingConfiguration.RegisterWellKnownClientType(typeof(MyClass), url);
#endregion //类型使用
MyClass myclass = new MyClass();
myclass.Count();
MyClass myclass1 = new MyClass();
myclass1.Count();
图 1

因为这里使用的是服务器SingleCall类型模式激活的,所以对象状态是不保存的,就跟上面那一小节定义的一样,只有在方法调用的时候才会被创建,方法调用完毕则会被释放销毁,但是也可以在宿主服务端使用变量来记录状态。现在可以在宿主服务端(服务器端)注册类型的时候把激活模式换成Singleton的再来看一下结果:
这是编程式的示例代码,下面给大家演示配置式的。
3.配置式:
宿主服务端(服务器端)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services; using System.Threading; using RemoteServer; namespace RemoteServerHost #region 配置式宿主服务端注册 信道和对象类型
Console.WriteLine("开始注册Http信道");
RemotingConfiguration.Configure(AppDomain.CurrentDomain.FriendlyName + ".config");
Console.WriteLine("Http信道注册完成————————————————");
#endregion
这里只要使用.NET给我们提供的RemotingConfiguration类型中的Configure()方法来加载配置文件就行了,注册信道的类型,远程对象的激活方式和模式都是在配置文件中注册的,来看配置文件信息:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="http" port="8004"/>
</channels>
<service>
<wellknown mode="Singleton" type="RemoteServer.MyClass,RemoteServer" objectUri="RTMyClass" />
</service>
</application>
</system.runtime.remoting>
</configuration>
这里配置文件中,是准备注册http类型的信道,并且把远程对象注册为服务器激活类型(wellKnow)Singleton激活模式,宿主服务端的就这么多,接下来看客户端的.
客户端
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services; using System.Threading; using RemoteServer; namespace RemoteClient #region 配置式本地注册
Thread.Sleep(new TimeSpan(, , ));
Console.WriteLine("开始客户端注册类型");
RemotingConfiguration.Configure(AppDomain.CurrentDomain.FriendlyName + ".config", false);
#endregion
//类型使用
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
MyClass myclass = new MyClass();
myclass.Count();
MyClass myclass1 = new MyClass();
myclass1.Count();
跟宿主服务端的一样,使用Configure()方法来注册远程对象,但是本地的配置文件怎么配置呢?不着急的,一起来看:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown type="RemoteServer.MyClass,RemoteServer" url="http://localhost:8004/RTMyClass"/>
</client>
</application>
</system.runtime.remoting>
</configuration>
客户端 要注册的 远程对象类型 的 激活类型(客户端激活、服务器端激活) 是要跟宿主服务端的相对应。
这次换了Singleton模式
图2

4.远程回调
宿主服务端:
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services;
using System.Threading; using RemoteServer;
namespace RemoteServerHost #region 远程回调
Console.WriteLine("开始Tcp注册信道");
BinaryServerFormatterSinkProvider formatter = new BinaryServerFormatterSinkProvider();//二进制格式化器
formatter.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;//设置过滤类型为Full IDictionary channel = new Hashtable();
channel["name"] = "RWCTmyclass";
channel["port"] = ; IChannel tcpChannel = new TcpChannel(channel, null, formatter);
ChannelServices.RegisterChannel(tcpChannel, false);//注册Tcp类型信道
Console.WriteLine("Tcp信道注册完成————————————————");
Console.WriteLine("开始 服务器激活类型Singleleton模式的宿主服务器端类型注册");
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass", WellKnownObjectMode.Singleton);
Console.WriteLine("类型注册完成");
#endregion Thread.Sleep(new TimeSpan(, , )); Console.WriteLine("释放Tcp信道");
ChannelServices.UnregisterChannel(tcpChannel);
客户端: using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Services; using System.Threading; using RemoteServer; namespace RemoteClient #region 远程回调
Thread.Sleep(new TimeSpan(, , ));
IChannel tcp = new TcpChannel();
ChannelServices.RegisterChannel(tcp, false);
string url = "tcp://localhost:8003/RWCTmyclass";
Console.WriteLine("开始客户端注册类型");
RemotingConfiguration.RegisterWellKnownClientType(typeof(MyClass), url);
#endregion Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
MyClass myclass = new MyClass();
myclass.Count();
EventMehtodClass methodclass = new EventMehtodClass();
myclass.NumberChanged += methodclass.OnNumberChanged;
Thread.Sleep();
myclass.OnNumberChanged();
图-3

在Singleton激活方式下是可以完成远程回调的,但是用Singlecall模式的话则不行,因为如果是这样的话,之前对远程对象(服务器对象)的操作都没有状态保存,上面说到过,Singlecall模式是一来一回则被释放掉了,本地客户端仅仅是保留了一个代理。可以验证一下:
修改宿主服务端的代码Singleton改为SingleCall
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass", WellKnownObjectMode.SingleCall);
修改客户端的代码 myclass.Count();又新加一句
MyClass myclass = new MyClass();
myclass.Count();
myclass.Count();
EventMehtodClass methodclass = new EventMehtodClass();
myclass.NumberChanged += methodclass.OnNumberChanged;
Thread.Sleep();
myclass.OnNumberChanged();
修改后的运行结果:
图4

为什么没有像图1中的那样发生回调这里已经不用说明了。
作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
.Net组件程序设计之远程调用(二)的更多相关文章
- .Net组件程序设计之远程调用(一)
.Net组件程序设计之远程调用(一) 1应用程序域 我们知道我们写的C#代码是在操作系统逻辑体系结构中最上层的,然而操作系统本身是不会认识C#代码的,它只认识机器代码.那我们写的程序经过编译后是编译成 ...
- .Net组件程序设计之异步调用
.Net组件程序设计之异步调用 说到异步调用,在脑海中首先想到就是BeginInvoke(),在一些常用对象中我们也会常常见到Invoke()和BeginInvoke(), 要想让自己的组件可以被客户 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- zookeeper系列之七—从远程调用认识zookeeper
http://www.csdn.net/article/2014-01-02/2817944-zookeeper 在Hadoop的学习过程中,Zookeeper是让很多初学者困惑的技术,远程调用服务是 ...
- .NET组件程序设计之线程、并发管理(二)
.Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后 ...
- 如何从零开始实现一个soa远程调用服务基础组件
说起soa远程调用基础组件,最著名的莫过于淘宝的dubbo了,目前很多的大型互联网公司都有一套自己的远程服务调用分布式框架,或者是使用开源的(例如dubbo),或者是自己基于某种协议(例如hessia ...
- Dubbo源码学习总结系列二 dubbo-rpc远程调用模块
dubbo本质是一个RPC框架,我们首先讨论这个骨干中的骨干,dubbo-rpc模块. 主要讨论一下几部分内容: 一.此模块在dubbo整体框架中的作用: 二.此模块需要完成的需求功能点及接口定义: ...
- .NET连接SAP系统专题:SAP中新建可远程调用的RFC(二)
何谓RFC,就是一个Function,可以被非SAP系统调用,比如VB,C#,Java等.如果我们在RFC中INCLUDE了相关的业务逻辑,那么我们就可以完全操控SAP中的业务数据了.就像在TTE里, ...
- SpringCloud(二) - Eureka注册中心,feign远程调用,hystrix降级和熔断
1.项目模块介绍 2. 父项目 主要依赖 spring-cloud 的 版本控制 <properties> <!-- springCloud 版本 --> <scd.ve ...
随机推荐
- java中的泛型的使用与理解
什么是泛型? 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写 体验泛型代码时定义一些可变部份,那些部份在使用前必须作出指明.各种程序设计语言和其编译器.运行环境对泛型的支持均不一样 ...
- maven打包时,依赖包打不进jar包中
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- InnoDB还是MyISAM 再谈MySQL存储引擎的选择
两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...
- supervisor-1:基础篇
别人博客转载,做个记录 原文链接:http://lixcto.blog.51cto.com/4834175/1539136 有阵子没写博客了,这段时间一直在研究python django框架和前端相关 ...
- Daily Scrum Meeting ——FourthDay(Beta)12.12
一.Daily Scrum Meeting照片 讨论界面优化详情 二.Burndown Chart 项目有条不紊地进行中... 1.新增6个界面修改计划 2.修复两个BUG 三.项目进展(check- ...
- OSG消息机制之事件处理概述
OSG的消息机制包括好多个头文件预定义及多个类. 首先,消息接收相关的类当属osgGA::GUIEventHandler和osgGA::GUIEventAdapter这两个类了.前者处理OSG程序与用 ...
- HttpClient发送Get和Post请求
package JanGin.httpClient.demo; import java.io.IOException; import java.io.UnsupportedEncodingExcept ...
- Spring 使用 SLF4J代替 Commons Logging 写日志 异常
项目的日志更换成slf4j和logback后,发现项目无法启动.错误提示 Caused by: java.lang.NoClassDefFoundError: Lorg/apache/commons/ ...
- 求50-100内的素数(java)
实现代码: public class sushu { public static void main(String[] args) { for(int i=50 ; i<=100; i++){ ...
- div高度根据内容自动增大
1.很多时候我们希望容器高度能够自适应内部元素的变化,需要用到min-height属性. 2.有时候用了min-height还是不会随着内容自适应高度,您需要检查下容器的子元素是不是有浮动属性,当子元 ...