很久没有写博客了,最近因为公司项目关系,学习了.net remoting.闲暇之余,想与大家分享一下(可能是一个系列哦)。
一.学习remoting前,要搞懂的知识
1.应用程序域:
所有的.Net 应用程序都运行在托管环境(managed environment)中,但操作系统只提供进程(Process)
供程序运行,而进程只是提供了基本的内存管理,它不了解什么是托管代码。所以托管代码, 也可以说是我们
创建的C#程序,是无法直接运行在操作系统进程中的。为了使托管代码能够运行在非托管的进程之上 ,就需要
有一个中介者,这个中介者可以运行于非托管的进程之上,同时向托管代码提供运行的环境。这个中介者就是应
用程序域(Application Domain ,简写为App Domain)。所以我们的.Net程序,不管是Windows窗体、Web
窗体、控制台应用程序,又或者是一个程序集,总是运行在一个App Domain中 (看了不少文章,感觉这个定义
比较合适)
2.应用程序域与进程的关系:
从概念1得知,使用.net建立的可执行程序(*.exe),并没有承载在进程中,而是承载在应用程序域中,一个进
程可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序或多个程序集,应用程序域可以看作轻量
级的进程,它具有进程的深度隔离,并且比进程占用的资源更少,这就如iis工作进程w3wp.exe(iis6.0,iis 5.0时
是aspnet_wp.exe)承载多个站点不是创建多个进程,而是创建多个应用程序域一样。
3.应用程序域与线程的关系:
应用程序域和线程之间不具有一对一的相关性。在任意给定时间段内,在单个应用程序域中可以执行几个线程
,而且特定线程并不局限在单个应用程序域内。也就是说,线程可以自由跨越应用程序域边界;不为每个应用程序域
创建新线程。在任意时刻, 每一线程都在只能在一个应用程序域中执行。运行库会跟踪在哪些应用程序域中有哪些
线程正在运行。
4.应用程序域的总体概括 :
在.net出现以前,一个进程下,只能运行一个应用程序,而在.net出现后,一个进程下, 可以运行多个应用程序.
这都是因为应用程序域的出现。
以前使用进程边界来隔离在同一台计算机上运行的应用程序。每一个应用程序被加载到单独的进程中,这样就将
该应用程序与在同一台计算机上运行的其他应用程序相隔离。
隔离这些应用程序的原因在于内存地址是与进程相关的;在目标进程中,不能通过任何有意义的方式使用从一个进
程传递到另一个进程的内存指针。此外,您不能在两个进程间进行直接调用。您必须代之以使用代理,它提供一定程
度的间接性。
如果只有一个类库程序集(.dll文件),是无法启动一个进程的(它并非可执行文件)。所以,创建进程需要加载一个
可执行程序集(Windows 窗体、控制台应用程序等.exe文件)。当可执行程序集加载完毕,.Net会在当前进程中创建
一个新的应用程序域,称为默认应用程序域。一个进程中只会创建一个默认应用程序域, 这个应用程序域的名称与
程序集名称相同。默认应用程序域不能被卸载,并且与其所在的进程同生共灭.
那么应用程序域是如何提供托管环境的呢?简单来说,应用程序域只是允许它所加载的程序集访问由.Net Runti
me所提供的服务。这些服务包括托管堆(Managed Heap),垃圾回收器(Garbage collector),JIT 编译器等.Net底
层机制,这些服务本身(它们构成了.Net Runtime)是由非托管C++实现的.
5.net remoting的必要性:
在一个应用程序域中运行的代码不能直接访问其他应用程序域中的代码或资源。为了强制实施此隔离,公共语言
运行库禁止在不同应用程序域中的对象之间进行直接调用。而在某些情况下,我们需要跨过应用程序域,与另外的应
用程序域进行通信,即穿越边界。remoting就是解决该问题的技术之一.它提供了一种对象通过应用程序域与另一对
象进行交互的框架.
二.remoting体系结构
假定您的应用程序在一台计算机上运行,而您想使用由存储在另一台计算机上的类型公开的功能。下面的插图显示了常规的
远程处理过程。
如果关系的双方均配置正确,则客户端仅创建服务器类的一个新实例。远程处理系统创建一个表示该类的代理对象, 并向
客户端对象返回一个对该代理的引用。当客户端调用方法时,远程处理基础结构将处理调用,检查类型信息,并通过信道将
该调用发送到服务器进程。侦听信道获得该请求,并将其转发给服务器远程处理系统,服务器远程处理系统查找(或在必要
时创建)并调用被请求的对象。然后,此过程将反向进行,服务器远程处理系统将响应捆绑成消息,并由服务器信道发送到
客户端信道。最后,客户端远程处理系统通过代理将调用的结果返回给客户端对象。
通道是一个承载数据流、根据特定网络协议创建包并将该包发送到另一台计算机的类型
下图是客户端请求一个方法的流程图(摘自网络)
三.remoting小示例
1.提供服务对象的类库项目:Hello
namespace Hello { public class HelloServer:MarshalByRefObject { public HelloServer() { Console.WriteLine("Hello Server"); } public void SayHello(String s) { Console.WriteLine("Hello"+s); } } }
2.服务端项目:Server
namespace Server { class Program { static void Main(string[] args) { try { TcpChannel tcl = new TcpChannel(4000); ChannelServices.RegisterChannel(tcl, false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(Hello.
HelloServer), "SayHello", WellKnownObjectMode.SingleCall); Console.WriteLine("listing Begin!"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }
3.客户端项目:Client
namespace Client { class Program { static void Main(string[] args) { TcpChannel tcl = new TcpChannel(); ChannelServices.RegisterChannel(tcl,false); Hello.HelloServer hobj = (Hello.HelloServer)Activator.
GetObject(typeof(Hello.HelloServer), "tcp://localhost:4000/SayHello"); if (hobj == null) { System.Console.WriteLine("Can't Find Server"); } else { System.Console.WriteLine(hobj.SayHello("shang hai")); } Console.ReadLine(); } } }
备注声明:以上部分资源来源于网络,由于转载复杂,无法确定原作者,故未注明出处.在此一并感谢。