Remoting入门
前几天接到一个项目,是一个分布式系统。本人从来就没做过分布式系统,凭着几年的开发经验。仔细分析了需求。得出有两个解决方案;一是Webservice和.Net Remoting。最后选择了Remoting。至于在这两个技术中如何去选择,网上能找到很多相关资料,我也会在后续的文章写一点。
本文作为一篇入门级的文章,结合自己的经验,和大家一起来认识下Remoting。在这里我们不阐述很多的理论。用一个实际的例子来说明。用remoting大概可以分为这么三步走:
1. 首先建立一个远程对象RemotingObject首先我们建立类库工程RemotingObject。加入一个类文件。加入如下代码:
using System;
using System.Data;
using System.Data.SqlClient;
using BeatFate.Data;
namespace BeatFate.Data.Remoting.Object
{
[SerializableAttribute]
public sealed class DataAccess : MarshalByRefObject
{
private string StringValue = "This is the RemotableType.";
public string StringMethod() {
return StringValue;
}
}
}
这里做几点说明:
a. 所有远程对象类必须继承自MarshalByRefObject
b. 如果必要的情况我们必须序列化该类,所以必需加上元属性[SerializableAttribute]
c. 我这个类是用作数据库访问的基类所以引入了我自己的类,和一些相关的数据库类的引用。
2. 建立服务器类。我们可以建立一个WinForm应用程序。在该工程中我们要加入app.config配置文件和一个server类文件两个文件的代码分别是
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application name="BeatFateService">
<service>
<wellknown
mode="SingleCall"
type="BeatFate.Data.Remoting.Object.DataAccess,RemotingObject"
objectUri="DataAccessObject"/>
</service>
<channels>
<channel ref="tcp server" port="9898"/>
</channels>
</application>
<debug loadTypes="true"/>
<customErrors mode="off"/>
</system.runtime.remoting>
</configuration>
对配置文件做几个如下注释:
A.<application name="BeatFateService">这个name属性可以是任意的当然最好是一个您认为有意义的名字
B.<service>
<wellknown
mode="SingleCall"
type="BeatFate.Data.Remoting.Object.DataAccess,RemotingObject"
objectUri="DataAccessObject"/>
</service>
type="BeatFate.Data.Remoting.Object.DataAccess,RemotingObject"
BeatFate.Data.Remoting.Object.DataAccess整个类的完整名字
RemotingObject程序集名字。
在这里申明了生存期模型。在.NET Remoting
•客户端激活对象
•服务器激活对象
<channels>
<channel ref="tcp server" port="9898"/>
</channels>
通道申明在.NET Remoting通道主要有两种:Tcp和Http,找一个没有使用的端口注册一个端口
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
//using System.Runtime.Remoting.Channels.Tcp;
namespace Server {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
RemotingConfiguration.Configure("Server.exe.config",false);
// TcpChannel chan = new TcpChannel(8085);
// ChannelServices.RegisterChannel(chan);
// RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("RemotingSamples.HelloServer,Object"), "SayHello", WellKnownObjectMode.SingleCall);
}
}
}
在框架中注册远程对象时,需要以下四项信息:
•包含类的程序集名称。
•远程对象的类型名称。
•客户端定位对象时将使用的对象 URI。
•服务器激活所需的对象模式。该模式可以是 SingleCall,也可以是 Singleton。
3.建立客户端类,我们也可以建立一个WinForm应用程序。在该工程中我们要加入app.config配置文件和一个client类文件两个文件的代码分别是
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- .NET Remoting configuration -->
<system.runtime.remoting>
<application name="Textile">
<client>
<wellknown type="BeatFate.Data.Remoting.Object.DataAccess,RemotingObject" url="tcp://localhost:9898/DataAccessObject" />
</client>
<channels>
<channel ref="tcp client" />
</channels>
</application>
</system.runtime.remoting>
<appSettings>
<add key="ServiceURL" value="tcp://localhost:9898/DataAccessObject"/>
</appSettings>
</configuration>
对这个配置文件我也作一些简单的说明:
A.<wellknown type="BeatFate.Data.Remoting.Object.DataAccess,RemotingObject"同前面服务器中的配置文件。
B.url="tcp://localhost:9898/DataAccessObject" />就是服务器地址加上端口号再加上服务器配置文件中申明的objectUri="DataAccessObject"/>
而<appSettings>
<add key="ServiceURL" value="tcp://localhost:9898/DataAccessObject"/>
</appSettings>
是我自己加上去的,方便程序中读取也方便修改
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
//using System.Runtime.Remoting.Channels.Tcp;
using BeatFate.Data.Remoting.Object;
namespace Client {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
string s = "";
//RemotingConfiguration.Configure("Client.exe.config");
//HelloServer obj = new RemotingSamples.HelloServer();
Console.WriteLine("开始远程调用");
DataAccess obj = (DataAccess)Activator.GetObject(typeof(DataAccess), ConfigurationManager.AppSettings["ServiceURL"]);
System.Console.WriteLine("远程调用的地址:" + ConfigurationManager.AppSettings["ServiceURL"]);
if (obj == null) System.Console.WriteLine("Could not locate server");
else s = obj.StringMethod();
}
}
}
然后分别在服务器和客户端项目中加入RemotingObject类库的引用。
先运行服务器程序然后再运行客户端程序,服务器和客户端可以运行在同一网络上的不同机器上。当然我上面是用tcp实现所以不能穿透防火墙。
由于时间仓促,很多东西可能都没讲清楚,如果有疑问可以email给我:percypeng2000@126.com来信回复,有时间的话我也会将我理解的东西再进去,当然也希望大家批评指正。这个是在blog园里的处女作,只希望他能给大家带来一定的信息我就很满足了。