.net Remoting的一个具体实现例子
这里.net remoting 的想实现一个银行转帐的过程
把用户输入的金额从用户A转入到用户B
数据库:
使用SQL SERVER里面的那个Pubs数据库,在这个数据库里面创建一个数据表叫Budget
只包含两个字段,Name、Money
CREATE TABLE Budget
(
NAME VARCHAR(8) NOT NULL,
MONEY FLOAT
)
GO
服务器端:
只需要创建一个普通的Win32窗体即可
用于启动服务器的服务
这段代码只是在宿主服务器上启动一个Remoting服务端口或者是在Tcp或者是在Http上
{
ChannelServices.RegisterChannel(new HttpChannel(7608));
ChannelServices.RegisterChannel(new TcpChannel(7711));
RemotingConfiguration.ApplicationName="TranserRemotingService";
//如果这个宿主程序是注册在IIS上的话,那么这个ApplicationName就相当于IIS上的虚拟目录
WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(typeof(TransferMoney),"URLAssemblyComponent",WellKnownObjectMode.Singleton);
RemotingConfiguration.RegisterWellKnownServiceType(WKSTE);
bttnStart.Enabled=false;
}
private void button2_Click(object sender, System.EventArgs e)
{
Close();
}
下面这段代码就是Remoting服务的最重要的部分,具体实现都是在这里实施
其中“TransMoney”是一个存储过程,它做了把钱从A的帐户转到B的实际操作
{
public string getTransferResult(double money)
{
try
{
transferMoneyFromAToB(money);
return "Transfer Money Succeed!";
}
catch(Exception Ex)
{
return "Transfer Money Failed! "+Ex.Message;
}
}
private static void transferMoneyFromAToB(double money)
{
SqlCommand sqlcom =new SqlCommand("Exec TransMoney "+money.ToString()+",'A','B'");
databaseAccess obj=new databaseAccess();
sqlcom.Connection=obj.getConnection();
sqlcom.Connection.Open();
sqlcom.ExecuteNonQuery();
sqlcom.Connection.Close();
//throw new Exception("Operation failed when transfer money into A!");
}
}
这就是那个存储过程,考过去就可以用了
@Money float,
@FromUser varchar(8),
@ToUser varchar(8)
)
as
begin
begin tran
update budget set Money=Money-@Money where Name =@FromUser
if @@Error<>0
begin
rollback tran
RaisError ('妈的给钱时银行柜员机出错了!:( ', 16, 1) with Log --记录日志
return -1
end
update budget set Money=Money+@Money where Name =@ToUser
if @@Error<>0
begin
rollback tran
RaisError ('妈的收钱时银行柜员机出错了!:( ', 16, 1) with Log --记录日志
return -1
end
commit tran
return 1
end
这里还要注意一个类“databaseAccess”需要加入到项目中去,代码如下:
using System.Data.SqlClient;
namespace RemotingConsole
{
/// <summary>
/// The databaseAccess sets up the connection to the data repository.
/// </summary>
/// <remarks>
/// Author: Ansel Du; arkstars@hotmail.com; Mar. 2005
/// </remarks>
public class databaseAccess
{
private static string sqlConnectionString = "server=61.129.112.20;database=Pubs;User ID=sa;Password=";
private SqlConnection sqlConnection;
/// <summary>
/// Public class constructor.
/// </summary>
protected internal databaseAccess()
{
sqlConnection = new SqlConnection(databaseAccess.sqlConnectionString);
}
/// <summary>
/// The getConnection method sets up the database connection
/// </summary>
/// <returns>the (closed) SQL connection object</returns>
protected internal SqlConnection getConnection() //组合体内子类也可见
{
return sqlConnection;
}
}
}
但是大家可能注意到了在Remoting的服务那一段代码里面有一个接口"ITransfer"
public class TransferMoney:MarshalByRefObject,ITransfer
...
对,我为了让客户端容易而且安全地调用宿主服务器的服务,故意设了一个接口,这个接口需要你单独在创建一个项目来完成它:
namespace AssemblyComponent
{
/// <summary>
/// 定义一个接口
/// </summary>
public interface ITransfer
{
string getTransferResult(double money);
}
}
这个接口你创建了以后,生成一个Assembly(组合体)的DLL形式的东东
这个东东首先需要Remoting进行引用,而且服务器需要实现这个接口,具体实现上面的代码已经写了,你可以对照着看看就明白了。相信大家一定比我聪明!
然后生成,服务器端的服务这就完成了,这时候生成了一个Exe的组合文件,用户只需要那个Assembly文件和这个可执行的组合文件。那么就可以启动一个服务器了!
Ok!下面我们编写一个客户端来调用这个服务器的服务。
这个就是客户端的界面,很简单吧?这时候用户只需输入宿主服务器的IP和要转帐的金额数,选择一个传输通道TCP通道或者HTTP通道即可完成操作。
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using AssemblyComponent;
namespace remotingClient
{
.......
private void button1_Click(object sender, System.EventArgs e)
{
string msg;
try
{
double atemp=Convert.ToDouble(tBMoney.Text);
}
catch(Exception exx)
{
msg="输入的并非数字类型-〉 "+ exx.Message;
}
try
{
//通过Activator.GetObject得到代理类的实例
if(rbtHttp.Checked==true)//Http信道
{
ITransfer ProxyObj=(ITransfer) Activator.GetObject(typeof(ITransfer),"http://"+tbHostServer.Text+":7608/TranserRemotingService/URLAssemblyComponent");
double atemp=Convert.ToDouble(tBMoney.Text);
msg=ProxyObj.getTransferResult(Convert.ToDouble(atemp));
}
else//Tcp信道
{
ITransfer ProxyObj=(ITransfer) Activator.GetObject(typeof(ITransfer),"tcp://"+tbHostServer.Text+":7711/TranserRemotingService/URLAssemblyComponent");
double atemp=Convert.ToDouble(tBMoney.Text);
msg=ProxyObj.getTransferResult(Convert.ToDouble(atemp));
}
//msg=ProxyObj.a(2);
}
catch(Exception Ex)
{
msg="转帐失败-〉 "+ Ex.Message;
}
MessageBox.Show(msg);
}
private void Form1_Load(object sender, System.EventArgs e)
{
rbtTcp.Checked=true;
rbtHttp.Checked=false;
}
private void button2_Click(object sender, System.EventArgs e)
{
Close();
}
private void rbtTcp_CheckedChanged(object sender, System.EventArgs e)
{
rbtHttp.Checked=!rbtTcp.Checked;
}
private void rbtHttp_CheckedChanged(object sender, System.EventArgs e)
{
rbtTcp.Checked=!rbtHttp.Checked;
}
}
}
Ok,好像不缺少什么东西了,慢慢看吧,是不是很简单哦