Ansel's Blog

It would probably render the application more complex

博客园 首页 新随笔 联系 订阅 管理



.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上

        private void bttnStart_Click(object sender, System.EventArgs e)
        
{
            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 class TransferMoney:MarshalByRefObject,ITransfer
        
{
            
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!");
            }


        }


这就是那个存储过程,考过去就可以用了
CREATE Proc TransMoney(
@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;
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
...
对,我为了让客户端容易而且安全地调用宿主服务器的服务,故意设了一个接口,这个接口需要你单独在创建一个项目来完成它:

using System;


namespace AssemblyComponent
{

    /// 
<summary>
    /// 定义一个接口
    /// 
</summary>
    public interface ITransfer 
    {
        string getTransferResult(double money);
    }
}

这个接口你创建了以后,生成一个Assembly(组合体)的DLL形式的东东
这个东东首先需要Remoting进行引用,而且服务器需要实现这个接口,具体实现上面的代码已经写了,你可以对照着看看就明白了。相信大家一定比我聪明!
 
然后生成,服务器端的服务这就完成了,这时候生成了一个Exe的组合文件,用户只需要那个Assembly文件和这个可执行的组合文件。那么就可以启动一个服务器了!
Ok!下面我们编写一个客户端来调用这个服务器的服务。

这个就是客户端的界面,很简单吧?这时候用户只需输入宿主服务器的IP和要转帐的金额数,选择一个传输通道TCP通道或者HTTP通道即可完成操作。

using System;
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,好像不缺少什么东西了,慢慢看吧,是不是很简单哦

posted on 2005-08-17 15:31  Ansel  阅读(2792)  评论(9编辑  收藏  举报