第11章 .NET Remoting
11.1理解remoting
11.1.1应用程序域基本概念
.NET提供了一项技术,使得跨应用程序域中的对象也可以相互访问,该技术就是.NET remoting。(185)
11.1.2应用程序域的基本操作
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Threading;
using ClassLib;
using System.Runtime.Remoting; namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
////获取当前代码所在的应用程序域
//AppDomain currentDomain = AppDomain.CurrentDomain;
//currentDomain = Thread.GetDomain(); ////获取应用程序域名称
//string name = AppDomain.CurrentDomain.FriendlyName; ////创建新应用程序域
//AppDomain newDomain = AppDomain.CreateDomain("NewDomain"); ////在应用程序域中创建对象
//DemoClass obj = (DemoClass)AppDomain.CurrentDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass");
//ObjectHandle objHandle = AppDomain.CurrentDomain.CreateInstance("ClassLib", "ClassLib.DemoClass");
//obj = (DemoClass)objHandle.Unwrap(); ////判断是否为默认应用程序域
//bool isdefault = newDomain.IsDefaultAppDomain();
//string _path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; //Test1();
Test2();
Console.Read();
} static void Test1()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
DemoClass obj;
obj = (DemoClass)currentDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass");
obj.ShowAppDomain();
obj.ShowCount("Jimmy");
obj.ShowCount("Jimmy");
} static void Test2()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
AppDomain newDomain = AppDomain.CreateDomain("NewDomain");
DemoClass obj, obj2;
obj = (DemoClass)newDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass"); ;
obj.ShowAppDomain();
obj.ShowCount("Jimmy");
obj.ShowCount("Jimmy"); obj2 = (DemoClass)newDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass"); ;
obj2.ShowAppDomain();
obj2.ShowCount("Jimmy");
obj2.ShowCount("Jimmy");
}
}
}
11.2 Remoting架构
11.2.3 Remoting对象的三种激活方式
1.客户端激活(Client activated)
2.服务端激活Singleton(Server activated Singleton)
3.服务端激活SingleCall(Server activated SingleCall)(WKO)
11.3 Remoting程序的基本操作
11.3.1 服务程序集
11.3.2 服务端应用程序
1.注册通道
对于同一个应用程序域,同一名称的通道只能注册一次。对于同一机器,同一端口只能使用一次。
2.注册类型
3.对象位置
11.3.3 客户端应用程序
1.使用new操作符创建远程对象
2.其他创建远程对象的方法
11.3.4 程序运行测试
1.客户端激活方式
(1)不管是对象的创建,还是对象方法的执行,都位于远程服务端。
(2)服务端为每一个客户端创建其专属的对象,为这个客户提供服务,并且保存状态。
(3)可以从远程获取到方法执行的返回值
当使用客户激活方式时,远程对象在调用new操作时创建
2.服务端激活方式-singleton
3.服务端激活方式-singletCall
11.4 Remoting中的传值封送
11.5 分离服务程序集元数据和代码实现
11.5.1 使用接口分离服务程序集
使用接口分离程序集的方式无法创建客户激活对象(202)
11.5.2 使用“空类”分离服务程序集
11.5.3 使用Soapsuds.exe分离程序集
11.5.4 使用工厂方法实现分离
ServerConsole
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting;
using System.Collections;
using ServerAssembly; namespace ServerConsole
{
class Program
{
static void Main(string[] args)
{
RegisterChannel();
//RegisterChannel2();
RemotingConfiguration.ApplicationName = "SimpleRemote";
ServerActivatedSingleCall();
ServerActivatedSingleton();
ClientActivated();
Console.WriteLine("服务开启,按任意键退出");
Console.ReadKey();
} private static void RegisterChannel()
{
IChannelReceiver tcpChnl = new TcpChannel();
ChannelServices.RegisterChannel(tcpChnl, false);
IChannelReceiver httpChnl = new HttpChannel();
ChannelServices.RegisterChannel(httpChnl, false);
} private static void RegisterChannel2()
{
IServerChannelSinkProvider formatter;
formatter = new BinaryServerFormatterSinkProvider();
IDictionary propertyDic = new Hashtable();
propertyDic["name"] = "CustomTcp";
propertyDic["port"] = ;
IChannel tcpChnl = new TcpChannel(propertyDic, null, formatter);
ChannelServices.RegisterChannel(tcpChnl, false);
} // 注册客户端激活对象 Client Activated Object
private static void ClientActivated()
{
Console.WriteLine("方式:Client Activated Object");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterActivatedServiceType(t);
} // 注册服务激活对象 SingleCall
private static void ServerActivatedSingleCall()
{
Console.WriteLine("方式:Server Activated SingleCall");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterWellKnownServiceType(t, "ServerSingleCall", WellKnownObjectMode.SingleCall);
} // 注册服务激活对象 Singleton
private static void ServerActivatedSingleton()
{
Console.WriteLine("方式:Server Activated Singleton");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterWellKnownServiceType(t, "ServerSingleton", WellKnownObjectMode.Singleton);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharedAssembly; namespace ServerAssembly
{
public class DemoClass : MarshalByRefObject
{
private int count = ;
public DemoClass()
{
Console.WriteLine("\n----- DomoClass Constructor -----");
} public void ShowCount(string name)
{
count++;
Console.WriteLine("{0},the count is {1}.", name, count);
} public void ShowAppDomain()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
} public int GetCount()
{
return count;
} public DemoCount GetNewCount()
{
return new DemoCount(count);
}
} //public class DemoClass : MarshalByRefObject
//{
// public void ShowCount(string name)
// {
// throw new Exception("只运行于服务端");
// } // public void ShowAppDomain()
// {
// throw new Exception("只运行于服务端");
// } // public int GetCount()
// {
// throw new Exception("只运行于服务端");
// } // public DemoCount GetNewCount()
// {
// throw new Exception("只运行于服务端");
// }
//} [Serializable]
public struct DemoCount
{
private readonly int count;
public DemoCount(int count)
{
this.count = count;
}
public int Count
{
get { return count; }
} public void ShowAppDomain()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace SharedAssembly
{
public interface IDemoClass
{
int GetCount();
void ShowAppDomain();
void ShowCount(string name);
DemoCount GetNewCount();
} [Serializable]
public struct DemoCount
{
private readonly int count;
public DemoCount(int count)
{
this.count = count;
}
public int Count
{
get { return count; }
} public void ShowAppDomain()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
}
}
}
ClientConsole
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using ServerAssembly; namespace ClientConsole
{
class Program
{
static void Main(string[] args)
{
//ClientActivated();
//ServerSingleton();
//ServerSingleCall();
//RunTest("CAO1");
//RunTest("CAO2");
//RunTest(); //IDemoClass obj1 = GetSingleCallObject();
//obj1.ShowCount("WKO1");
//obj1.ShowCount("WKO1");
//IDemoClass obj2 = GetSingletonObject();
//obj2.ShowCount("WKO2");
//obj2.ShowCount("WKO2"); RunTest("WKO1");
RunTest("WKO2");
Console.WriteLine("客户端运行结束,按任意键退出...");
Console.ReadKey();
} // 注册客户端激活
private static void ClientActivated()
{
Type t = typeof(DemoClass);
string url = "tcp://127.0.0.1:8501";
//string url = "tcp://127.0.0.1:8501/SimpleRemote";
RemotingConfiguration.RegisterActivatedClientType(t, url);
} // 注册服务端激活 SingleCall
private static void ServerSingleCall()
{
Type t = typeof(DemoClass);
string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleCall";
RemotingConfiguration.RegisterWellKnownClientType(t, url);
} // 注册服务端激活 Singleton
private static void ServerSingleton()
{
Type t = typeof(DemoClass);
string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleton";
RemotingConfiguration.RegisterWellKnownClientType(t, url);
} //GetObject激活方式(仅适用服务端激活)
private static DemoClass GetSingletonObject()
{
string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleton";
DemoClass obj = (DemoClass)Activator.GetObject(typeof(DemoClass), url);
return obj;
} //GetObject激活方式(仅适用服务端激活)
private static DemoClass GetSingleCallObject()
{
string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleCall";
DemoClass obj = (DemoClass)Activator.GetObject(typeof(DemoClass), url);
return obj;
} //CreateInstance激活方式
private static DemoClass GetClientActivatedObject()
{
string url = "tcp://127.0.0.1:8501/SimpleRemote";
object[] activationAtt = { new UrlAttribute(url) };
DemoClass obj = (DemoClass)Activator.CreateInstance(typeof(DemoClass), null, activationAtt);
return obj;
} //private static IDemoClass GetSingletonObject()
//{
// string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleton";
// IDemoClass obj = (IDemoClass)Activator.GetObject(typeof(IDemoClass), url);
// return obj;
//} //private static IDemoClass GetSingleCallObject()
//{
// string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleCall";
// IDemoClass obj = (IDemoClass)Activator.GetObject(typeof(IDemoClass), url);
// return obj;
//} //private static DemoClass GetClientActivatedObject()
//{
// string url = "tcp://127.0.0.1:8501/SimpleRemote";
// object[] activationAtt = { new UrlAttribute(url) };
// DemoClass obj = (DemoClass)Activator.CreateInstance(typeof(DemoClass), null, activationAtt);
// return obj;
//} //private static void RunTest(string objectName)
//{
// DemoClass obj = new DemoClass();
// obj.ShowAppDomain();
// obj.ShowCount(objectName);
// Console.WriteLine("{0}, the count is {1}.", objectName, obj.GetCount());
// obj.ShowCount(objectName);
// Console.WriteLine("{0}, the count is {1}.", objectName, obj.GetCount());
//} //private static void RunTest()
//{
// DemoClass obj = new DemoClass();
// obj.ShowAppDomain();
// obj.ShowCount("CAO");
// DemoCount myCount = obj.GetNewCount();
// myCount.ShowAppDomain();
// Console.WriteLine("count: {0}.", myCount.Count);
//} private static void RunTest(string objectName)
{
//DemoClass obj = GetClientActivatedObject();
//DemoClass obj = GetSingletonObject();
DemoClass obj = GetSingleCallObject();
obj.ShowAppDomain();
obj.ShowCount(objectName);
Console.WriteLine("{0}, the count is {1}.", objectName, obj.GetCount());
obj.ShowCount(objectName);
Console.WriteLine("{0}, the count is {1}.", objectName, obj.GetCount());
}
}
}
11.6 Remoting中的方法回调
11.6.1 远程回调方式说明
11.6.2 客户端类型和服务端类型
1.服务端类型
2.客户端类型
11.6.3 服务端、客户端会话模型
11.6.4 宿主应用程序
1.服务端宿主应用程序
2.客户端宿主应用程序
11.6.5 程序运行测试
1.运行一个客户端
2.运行多个客户端
3.关闭第一个客户端,再新建一个客户端
ShareAssembly
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices; namespace SharedAssembly
{
public delegate void NumberChangedEventHandler(string name, int count);
public class Server : MarshalByRefObject
{
private int count = ;
private string serverName = "SimpleServer";
public event NumberChangedEventHandler NumberChanged; // 触发事件,调用客户端方法
[MethodImpl(MethodImplOptions.Synchronized)]
public void DoSomething()
{
count++;
if (NumberChanged != null)
{
Delegate[] delArray = NumberChanged.GetInvocationList();
foreach (Delegate del in delArray)
{
NumberChangedEventHandler method = (NumberChangedEventHandler)del;
try
{
method(serverName, count);
}
catch
{
//Delegate.Remove(NumberChanged, del);//取消某一客户端的订阅
}
}
}
}
//// 直接调用客户端方法
public void InvokeClient(Client remoteClient, int x, int y)
{
int total = remoteClient.Add(x, y);
Console.WriteLine("Invoke client method: x={0}, y={1}, total={2}", x, y, total);
}
public void GetCount(Client remoteClient)
{
Console.WriteLine("Count value from client: {0}", remoteClient.Count);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace SharedAssembly
{
public class Client : MarshalByRefObject
{
private int count;
public int Add(int x, int y)
{
Console.WriteLine("Add callback: x={0}, y={1}.", x, y);
return x + y;
}
// 方式1:供远程对象调用
public int Count
{
get {
count++;
return count;
}
}
// 方式2:订阅事件,供远程对象调用
public void OnNumberChanged(string serverName, int count)
{
Console.WriteLine("OnNumberChanged callback:");
Console.WriteLine("ServerName={0}, Server.Count={1}", serverName, count);
}
}
}
ServerConsole
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Serialization.Formatters;
using System.Collections;
using System.Runtime.Remoting.Channels.Tcp;
using SharedAssembly; namespace ServerConsole1
{
class Program
{
static void Main(string[] args)
{
RemotingConfiguration.ApplicationName = "CallbackRemoting";
BinaryServerFormatterSinkProvider formatter;
formatter = new BinaryServerFormatterSinkProvider();
formatter.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary propertyDic = new Hashtable();
propertyDic["name"] = "CustomerTcpChannel";
propertyDic["port"] = ;
IChannel tcpChnl = new TcpChannel(propertyDic, null, formatter);
ChannelServices.RegisterChannel(tcpChnl, false); Type t = typeof(Server);
RemotingConfiguration.RegisterWellKnownServiceType(t, "ServerActivated", WellKnownObjectMode.Singleton);
Console.WriteLine("Server running, model: Singleton\n");
Console.ReadKey();
}
}
}
ClientConsole
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using SharedAssembly;
using System.Runtime.Remoting; namespace ClientConsole1
{
class Program
{
static void Main(string[] args)
{
IChannel chnl = new TcpChannel();
ChannelServices.RegisterChannel(chnl, false);
Type t = typeof(Server);
string url = "tcp://127.0.0.1:8502/CallbackRemoting/ServerActivated";
RemotingConfiguration.RegisterWellKnownClientType(t, url);
Server remoteServer = new Server();
Client localClient = new Client();
remoteServer.NumberChanged += localClient.OnNumberChanged;
remoteServer.DoSomething();
remoteServer.GetCount(localClient);
remoteServer.InvokeClient(localClient, , );
Console.ReadKey();
}
}
}
第11章 .NET Remoting的更多相关文章
- 读《编写可维护的JavaScript》第11章总结
这周也是拿到了同程的offer,从此走上了前端之路!感谢我的贵人们.再次纪念一下~! 第11章 不是你的对象不要动 11.1 什么是你的 你的对象:当你的代码创建了这些对象或者你有职责维护其他人的代码 ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- 高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群
高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群 libnet软件包<-依赖-heartbeat(包含ldirectord插件(需要perl-MailTools的rpm包)) l ...
- Linux就这个范儿 第11章 独霸网络的蜘蛛神功
Linux就这个范儿 第11章 独霸网络的蜘蛛神功 第11章 应用层 (Application):网络服务与最终用户的一个接口.协议有:HTTP FTP TFTP SMTP SNMP DNS表示层 ...
- 锋利的jQuery第2版学习笔记8~11章
第8章,用jQuery打造个性网站 网站结构 文件结构 images文件夹用于存放将要用到的图片 styles文件夹用于存放CSS样式表,个人更倾向于使用CSS文件夹 scripts文件夹用于存放jQ ...
- 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池
第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...
- C++ Primer 读书笔记:第11章 泛型算法
第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...
随机推荐
- Android开发-mac上使用三星S3做真机调试
之前一直未使用真机进行Android开发,为准备明天的培训,拿出淘汰下来的s3准备环境,竟然发现无法连接mac,度娘一番找到答案,如下:mac 系统开发android,真机调试解决方案(无数的坑之后吐 ...
- R语言向量
R语言基础:向量 心无咎 2012-04-02 13:37:00 向量(vector)1.seq():产生有规律的数列,间距省略时默认值为1. 例1:seq(10, 20, 0.5) ...
- smb:unrecognized service
[root@sycflash ~]#service smb status smb:unrecognized service 提示:smb:unrecognized service.这时你会按照常规的方 ...
- Mongodb故障转移
测试环境 四台测试服务器10.151.151.150:27017(主节点),10.151.151.151:27017(从节点),10.151.151.152:27018(从节点),10.151.151 ...
- 这些年正Android - 身在他乡
“从不敢想到想去做到,做到我想的,事实证明我并不像他们想象的那样脆弱.我只是需要一盏灯,一架钢琴,一支麦克风.曾经想象过做一名医生救死扶伤,也曾想过做律师,做记者,做奥运冠军,但是都没有结果.因为我最 ...
- 可变参数宏__VA_ARGS__和...
__VA_ARGS__ 是一个可变参数的宏(gcc支持).实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点).这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所 ...
- Iphone连接win10电脑正常, itunes无法识别解决
1.之前试过重装itunes, apple的两个服务也都已经启动. 2.但是设备管理器不显示移动设备或者usb的apple mobile device driver 3.解决:打开C:\Program ...
- 解决UITableView上计时器(Timer)的滑动问题
要想计时器(Timer)不因UITableView的滑动而停止工作,就得探讨一下RunLoop了. RunLoop本质和它的意思一样是运行着的循环,更确切的说是线程中的循环.它用来接受循环中的事件和安 ...
- Yaf框架下类的自动加载
前面两篇博客分别讲述了PHP自带的类加载和composer中类的自动加载,其实Yaf框架也实现了基于PSR0和PSR4的类的自动加载.根据我对Yaf下类的自动加载方式的理解写下这篇博客.由于接触Yaf ...
- 关于安卓开发当中通过java自带的HttpURLConnection访问XML的java.io.EOFException问题
刚接触安卓开发,试着写个小程序熟悉下,就写了天气预报的小程序,通过httpUrlConnection读流的方式来获取网络公共接口提供的天气XML信息.但在建立http连接时一直报java.io.EOF ...