程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET Remoting如何通過Remoting實現雙向通信(Bidirectional Communication)

.NET Remoting如何通過Remoting實現雙向通信(Bidirectional Communication)

編輯:關於.NET

Remoting是NET平台下比較成熟高效的分布式技術,我們習慣采用傳統的遠程 調用的方式使用Remoting。在客戶端所在的Application Domain,我們通過 Proxy(Transparent Proxy)遠程地跨Application Domain調用一個方法。當來 自Client端的調用請求通過Proxy到達Server端所在的Application Domain後, Remoting Infrastructure在Server 端激活(Activate)相應的遠程對象(一個 繼承子System.MarshalByRefObject類對象)——這裡僅僅以服務端 激活對象(Server Activated Object——SAO),然後再Server端執行相應的操作後把Result傳遞給Proxy,並最終到達Client。這是一種典型的 Request/Response的調用方式。

我之所以一直比較推崇在.NET平台下使 用Remoting而非XML Web Service是因為我覺得.NET Remoting是一種比較成熟的 分布式技術。它自身提供了XML Web Service很多不具備的特性,其中對雙向通 信的支持就是一個很好的體現。

相對於典型的Request/Response的消息 交換模式(Message Exchange Pattern——MEP),雙向通信實質上 是采用的Duplex的MEP。也就是說,Server端在執行操作的時候,可以回調 (Callback)Client端的操作(這個操作時再Client端的Application Domain中 執行的)。

現在我們來看如何一步一步實現在Remoting環境下的雙向通 信。在下面的Sample中,我們的邏輯是:調用一個數學計算的遠程調用,除了傳 遞相應的操作數之外,我們還傳遞一個對象,這個對象可以在Server端中回調 (Callback) 把運算結果在Client端顯示出來。

Step1:構建整個 Solution的整體構架。

Artech.DuplexRemoting.Contract:Class Library Project,定義遠程對象(Remote Object)和Callback對象的Contract (Interface)。實際上,站在Server端的角度上看,Callback的操作是在 Client端的Application Domain中執行的,所以從本質上講, Callback對象是 Server端的遠程對象。

之所以定義這樣一個Contract Project,其目的 主要有以下幾點:

1.如果沒有把遠程對象的Interface,對已某一個需 要調用這個遠程對象的Client來說,它必須引用遠程對象本身。從安全的角度考 慮,Server向Client過多暴露了操作的實現邏輯。如果我們把遠程操作的 Contract提取出來,Client只要引用這個Interface就可以了。

2.一般 來說,遠程對象的Contract相對時靜態的(static),而業務邏輯的實現則是經 常 變化的。因為Client只需要了解的是遠程對象的Contract,所在無論Server 端對遠程對象的實現作了多大的變動,對不回對Client產生任何影響。

Artech.DuplexRemoting.Remoting:Class Library Project,定義遠程 對象本身。由於遠程對象必須實現上邊定義的Contract。所以需要引用 Artech.DuplexRemoting.Contract。

Artech.DuplexRemoting.Hosting: Console Application Project,以Self-Host的方式Host Remoting。引用 Artech.DuplexRemoting.Remoting。

Artech.DuplexRemoting.Client: Console Application Project,引用Artech.DuplexRemoting.Contract。

Step 2 在Artech.DuplexRemoting.Contract中定義 Contract

IDuplexCalculator.cs

using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.DuplexRemoting.Contract
{
  public interface IDuplexCalculator
  {
    void Add(double x, double y, ICalculatorCallback callback);
  }
}

ICalculatorCallback.cs

using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.DuplexRemoting.Contract
{
  public interface ICalculatorCallback
  {
    void ShowResult (double x, double y, double result);
  }
}

Step 3 在Artech.DuplexRemoting.Remoting定義遠程對象

DuplexCalculatorRemoting.cs

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexRemoting.Contract;
namespace Artech.DuplexRemoting.Remoting
{
  public class DuplexCalculatorRemoting:MarshalByRefObject, IDuplexCalculator
   {
    IDuplexCalculator Memberspublic void Add(double x, double y, ICalculatorCallback callback)
    {
       Console.WriteLine("Invoke the method Add({0}, {1}).",x,y);
      double result = x + y;
       callback.ShowResult(x,y,result);
    }
     #endregion
  }
}

Step 4 在 Artech.DuplexRemoting.Hosting Host遠程對象

App.config

<configuration>
   <system.runtime.remoting>
    <application name="Calculator">
      <service>
        <wellknown mode="SingleCall"
               type="Artech.DuplexRemoting.Remoting.DuplexCalculatorRemoting,Art ech.DuplexRemoting.Remoting"
              objectUri="DuplexCalculator.soap" />
       </service>
      <channels>
         <channel ref="http" port="8080">
           <serverProviders>
             <provider ref="wsdl" />
             <formatter ref="binary" typeFilterLevel="Full" />
          </serverProviders>
           <clientProviders>
             <formatter ref="binary" />
           </clientProviders>
        </channel>
       </channels>
    </application>
   </system.runtime.remoting>
</configuration>

Program.cs

using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.DuplexRemoting.Hosting
{
  class Program
  {
    static void Main(string[] args)
    {
       System.Runtime.Remoting.RemotingConfiguration.Configure ("Artech.DuplexRemoting.Hosting.exe.config",false);
       Console.WriteLine("Calculator service has begun to listen ");
      Console.Read();
    }
  }
}

這裡需要特別注意的有以下兩點:

1.在定 義Channel是需要指定一個雙向Channel(Bi-Directional Channel)。系統給我 們定義一一系列的System-Defined Channel用於調用遠程對象。其中有一些只能 提供單向的通信——比如只支持Client到Server的通信,而另一些可 以提供雙向的通信——比如TCP Channel 和Http Channel.

2 .在ServerProvider Section,我們必須設置typeFilterLevel為Full。出於安 全的考量,Remoting提供了兩個反序列化級別(Level)——Low & Full。Low是默認的,如果把typeFilterLevel設為Low,Remoting之會反 序列化Remoting基本功能相關的對象。而設為Full則意味著Remoting會反序列化 所有類型。如果你想知道那些類型是在Low Level下被限制,請參考 http://msdn2.microsoft.com/en-us/library/5dxse167.aspx。

之所以要把typeFilterLevel為Full,是因為我們的遠程調用裡包含一 Callback對象,它實際上是一個繼承System.MarshalByRefObject類對象(這個 的對象將在Artech.DuplexRemoting.Client中定義)。而這個對象是不會再Low Level下被自動反序列化。

<channels>
         <channel ref="http" port="8080">
           <serverProviders>
             <provider ref="wsdl" />
             <formatter ref="binary" typeFilterLevel="Full" />
           </serverProviders>
           <clientProviders>
            <formatter ref="binary" />
           </clientProviders>
        </channel>
       </channels>
  public interface IDuplexCalculator
  {
    void Add(double x, double y, ICalculatorCallback callback);
  }

Step 4 在 Artech.DuplexRemoting.Client定義Callback對象和調用遠程對象

CalculatorCallbackHandler.cs

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexRemoting.Contract;
namespace Artech.DuplexRemoting.Client
{
  public class CalculatorCallbackHandler:MarshalByRefObject, ICalculatorCallback
  {
    ICalculatorCallback Memberspublic void ShowResult(double x, double y, double result)
    {
       Console.WriteLine("x + y = {2} where x = {0} and y = {1} ", x, y, result);
    }
    #endregion
   }
}

App.config

<configuration>
<system.runtime.remoting>
  <application>
     <channels>
      <channel ref="http" port="0">
         <clientProviders>
          <formatter ref="binary" />
         </clientProviders>
         <serverProviders>
          <formatter ref="binary" typeFilterLevel="Full" />
         </serverProviders>
       </channel>
    </channels>
   </application>
</system.runtime.remoting>
</configuration>

Program.cs

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexRemoting.Contract;
namespace Artech.DuplexRemoting.Client
{
  class Program
   {
    static void Main(string[] args)
    {
              System.Runtime.Remoting.RemotingConfiguration.Configure ("Artech.DuplexRemoting.Client.exe.config", false);
       InvocateDuplexCalculator ("http://localhost:8080/Calculator/DuplexCalculator.soap");< br />     }
    static void InvocateDuplexCalculator(string remoteAddress)
    {
      IDuplexCalculator proxy = (IDuplexCalculator)Activator.GetObject(typeof(IDuplexCalculator), remoteAddress);
      proxy.Add(1,2,new CalculatorCallbackHandler());
      Console.Read();
     }    
  }
}

這裡有兩點需特別注意的 :

1.由於Server端時跨Application Domain遠程地調用運行Client Application Domain中的Callback對象(Callback的執行實際是在Client而不在 Server),所以Callback對象應該是一個MarshalByRefObject對象。

2.上面我們以經提及,對於Server端了來說Callback對象實際上是一個遠程對象( 在Callback過程中Client端轉變成Server端,而Server端轉變成Client端)。 Server端需要注冊一些Channel用於Client訪問寄宿在Server端的遠程對象,同 理,Server需要Callback一個寄宿在Client端Application Domain中的Callback 對象,Client端需要注冊相應的Channel

3.和Server端一樣,我們必須 設置typeFilterLevel為Full。

到現在為止我們已經完成了所有的 Program,我們來運行一下。

1.運行 Artech.DuplexRemoting.Hosting

2.運行Artech.DuplexRemoting.Client

將遠程對象Host到IIS中

我們知道,Remoting有兩種Host方式 Self Host和IIS Host,上面我們把Remoting Host到一個Console Application 中; 現在我們把試著把它Host到IIS中。實際上我們要做的工作很簡單。

1.在IIS Manager中添加一個虛擬目錄對應 Artech.DuplexRemoting.Remoting文件夾, 假設此虛擬目錄的Alias為 Artech.DuplexRemoting

2.在Artech.DuplexRemoting.Remoting根目錄 下中(也就是在http://localhost/Artech.DuplexRemoting根目錄下)添加一個 Web.config,並添加類似於Artech.DuplexRemoting.Hosting/App.Config中 的 Remoting Configuration。

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"& gt;
   <system.runtime.remoting>
    <application>
      <service>
        <wellknown mode="SingleCall"
              type="Artech.DuplexRemoting.Remoting.DuplexCalculatorRemoting,Art ech.DuplexRemoting.Remoting"
              objectUri="DuplexCalculator.soap" />
       </service>
      <channels>
         <channel ref="http">
           <serverProviders>
            <provider ref="wsdl" />
            <formatter ref="binary" typeFilterLevel="Full" />
           </serverProviders>
           <clientProviders>
            <formatter ref="binary" />
           </clientProviders>
        </channel>
       </channels>
    </application>
   </system.runtime.remoting>
  <system.web>
     <compilation debug="true">
       <assemblies>
        <add assembly="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
         <add assembly="Microsoft.Transactions.Bridge, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
         <add assembly="SMDiagnostics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
         <add assembly="System.IdentityModel.Selectors, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
         <add assembly="System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
         <add assembly="System.Web.RegularExpressions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
         <add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
         <add assembly="System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
         <add assembly="System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
       </assemblies>
    </compilation>
   </system.web>
</configuration>

這樣我們 可以不需要Hosting,就可以運行Client了。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved