国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

簡(jiǎn)析JavaRMI與.NETRemoting

2019-11-18 16:25:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  java與.NET都提供了遠(yuǎn)程處理功能,但不完全相同.Java遠(yuǎn)程處理是通過(guò)一個(gè)“共享接口”實(shí)現(xiàn)的,而.NET可以通過(guò)一個(gè)“共享命令集”實(shí)現(xiàn)。下面就這兩種方式來(lái)具體說(shuō)明。

Java 遠(yuǎn)程處理

Java遠(yuǎn)程方法調(diào)用(RMI)提供了Java程序語(yǔ)言的遠(yuǎn)程通訊功能,這種特性使客戶機(jī)上運(yùn)行的程序可以調(diào)用遠(yuǎn)程服務(wù)器上的對(duì)象,使Java編程人員能夠在網(wǎng)絡(luò)環(huán)境中分布操作。
創(chuàng)建一個(gè)簡(jiǎn)單的Java分布式遠(yuǎn)程方法調(diào)用程序可以按以下幾個(gè)步驟操作,

一、定義遠(yuǎn)程接口:
在 Java 中,遠(yuǎn)程對(duì)象是實(shí)現(xiàn)遠(yuǎn)程接口的類的實(shí)例, 遠(yuǎn)程接口聲明每個(gè)要遠(yuǎn)程調(diào)用的方法。在需要?jiǎng)?chuàng)建一個(gè)遠(yuǎn)程對(duì)象的時(shí)候,我們通過(guò)傳遞一個(gè)接口來(lái)隱藏基層的實(shí)施細(xì)節(jié),客戶通過(guò)接口句柄發(fā)送消息即可。
遠(yuǎn)程接口具有如下特點(diǎn):
1) 遠(yuǎn)程接口必須為public屬性。如果不這樣,除非客戶端與遠(yuǎn)程接口在同一個(gè)包內(nèi),否則 當(dāng)試圖裝入實(shí)現(xiàn)該遠(yuǎn)程接口的遠(yuǎn)程對(duì)象時(shí),調(diào)用會(huì)得到錯(cuò)誤結(jié)果。
2) 遠(yuǎn)程接口必須擴(kuò)展接口java.rmi.Remote。
3) 除與應(yīng)用程序本身特定的例外之外,遠(yuǎn)程接口中的每個(gè)方法都必須在自己的throws從句中 聲明java.rmi.RemoteException。(或 RemoteException 的父類)。
4) 作為參數(shù)或返回值傳遞的一個(gè)遠(yuǎn)程對(duì)象(不管是直接,還是本地對(duì)象中嵌入)必須聲明為遠(yuǎn) 程接口,而不應(yīng)聲明為實(shí)施類。
下面是遠(yuǎn)程接口的接口RmiSample的定義

import java.rmi.*;
public interface RmiSample extends Remote {
     public int sum(int a,int b) throws RemoteException;
}

二、實(shí)現(xiàn)遠(yuǎn)程接口:
遠(yuǎn)程對(duì)象實(shí)現(xiàn)類必須擴(kuò)展遠(yuǎn)程對(duì)象java.rmi.UnicastRemoteObject類,并實(shí)現(xiàn)所定義的遠(yuǎn)程接口。遠(yuǎn)程對(duì)象的實(shí)現(xiàn)類中包含實(shí)現(xiàn)每個(gè)遠(yuǎn)程接口所指定的遠(yuǎn)程方法的代碼。這個(gè)類也可以含有附加的方法,但客戶只能使用遠(yuǎn)程接口中的方法。因?yàn)榭蛻羰侵赶蚪涌诘囊粋€(gè)句柄,而不是它的哪個(gè)類。必須為遠(yuǎn)程對(duì)象定義構(gòu)造函數(shù),即使只準(zhǔn)備定義一個(gè)默認(rèn)構(gòu)造函數(shù),用它調(diào)用基礎(chǔ)類構(gòu)造函數(shù)。因?yàn)榛A(chǔ)類構(gòu)造函數(shù)可能會(huì)拋出 java.rmi.RemoteException,所以即使別無(wú)它用必須拋出java.rmi.RemoteException例外。
以下是遠(yuǎn)程對(duì)象實(shí)現(xiàn)類的聲明:

  import java.rmi.*;
  import java.rmi.server.*;
  public class RmiSampleImpl extends UnicastRemoteObject
                           implements RmiSample {
      RmiSampleImpl() throws RemoteException {
         super();
      }
      public int sum(int a,int b) throws RemoteException {
         return a + b;
      }
  }

三、編寫(xiě)服務(wù)器類:
包含 main 方法的類可以是實(shí)現(xiàn)類自身,也可以完全是另一個(gè)類。下面通過(guò)RmiSampleServer 來(lái)創(chuàng)建一個(gè)遠(yuǎn)程對(duì)象的實(shí)例,并通過(guò)java.rmi.registry.LocateRegistry類的createRegistry 方法從指定端口號(hào)啟動(dòng)注冊(cè)服務(wù)程序,也可以通過(guò)執(zhí)行 rmiregistry 命令啟動(dòng)注冊(cè)服務(wù)程序,注冊(cè)服務(wù)程序的缺省運(yùn)行端口為 1099。必須將遠(yuǎn)程對(duì)象名字綁定到對(duì)遠(yuǎn)程對(duì)象的引用上: Naming.rebind("http://localhost:8808/SAMPLE-SERVER" , Server);
以下是服務(wù)器類的聲明:

import java.rmi.*;
import java.rmi.registry.*;
public class RmiSampleServer{
     public static void main(String args[]) {
         try {
         LocateRegistry.createRegistry(8808) ;
         SampleServerImpl Server = new SampleServerImpl();
         // 將該對(duì)象實(shí)例與名稱“SAMPLE-SERVER”捆綁
         Naming.rebind("http://localhost:8808/SAMPLE-SERVER" , Server);
         } catch (java.net.MalformedURLException me) {
            System.out.         } catch (RemoteException re) {
            System.out.println("Remote exception: " + re.toString());
         }
     }
  }

四、編寫(xiě)使用遠(yuǎn)程服務(wù)的客戶機(jī)類:
客戶機(jī)類的主要功能有兩個(gè),一是通過(guò)Naming.lookup方法來(lái)構(gòu)造注冊(cè)服務(wù)程序 stub 程序?qū)嵗钦{(diào)用服務(wù)器遠(yuǎn)程對(duì)象上的遠(yuǎn)程方法。
以下是服務(wù)器類的聲明:

import java.rmi.*;
import java.rmi.server.*;
public class RmiSampleClient {
     public static void main(String[] args)
     {
         try {
            String url = "http://localhost:8808/SAMPLE-SERVER";
            RmiSample RmiObject = (RmiSample)Naming.lookup(url);
            System.out.println(" 1 + 2 = " + RmiObject.sum(1,2) );
         } catch (RemoteException exc) {
             System.out.println("Error in lookup: " + exc.toString());
         } catch (java.net.MalformedURLException exc) {
             System.out.println("Malformed URL: " + exc.toString());
         } catch (java.rmi.NotBoundException exc) {
             System.out.println("NotBound: " + exc.toString());
         }
      }
   }

五、編譯代碼:
要編譯 Java 源文件,請(qǐng)運(yùn)行 javac 命令:
javac RmiSample.java RmiSampleImpl.java RmiSampleServer.java RmiSampleClient.java

六、為遠(yuǎn)程對(duì)象實(shí)現(xiàn)創(chuàng)建根和干:
要?jiǎng)?chuàng)建存根程序和骨架文件,應(yīng)以包含遠(yuǎn)程對(duì)象實(shí)現(xiàn)的已編譯類包全名運(yùn)行 rmic 編譯器。
存根(Stub)是遠(yuǎn)程對(duì)象在客戶端的代理,它將RMI調(diào)用傳遞給服務(wù)器端的骨架(Skeleton),后者負(fù)責(zé)將該調(diào)用傳遞給實(shí)際的遠(yuǎn)程方法輸入如下:
D:/RMI>rmic -d D:/RMI RmiSampleImpl 執(zhí)行這個(gè)命令, 若rmic成功運(yùn)行,RMI目錄下就會(huì)多出兩個(gè)新類: RmiSampleImpl_Stub.class RmiSampleImpl_Skel.class 它們分別對(duì)應(yīng)的是存根(stub)和骨架(skeleton).

七、運(yùn)行代碼:
運(yùn)行服務(wù)端程序:在Windows下,輸入下列命令,在后臺(tái)啟動(dòng)RmiSampleServer程序:
D:/RMI>java RmiSampleServer
運(yùn)行客戶端程序:
D:/RMI>java RmiSampleClient
客戶端輸出: 1 + 2 = 3

.NET 遠(yuǎn)程處理。

微軟的.NET Remoting提供了一種允許對(duì)象通過(guò)應(yīng)用程序域與另一對(duì)象進(jìn)行交互的框架,從結(jié)構(gòu)上而言,.NET Remoting對(duì)象非常適合通過(guò)網(wǎng)絡(luò)訪問(wèn)資源,而又無(wú)需處理由基于SOAP的WebServices所帶來(lái)的難題。下面介紹創(chuàng)建一個(gè)簡(jiǎn)單的.NET Remoting分布式遠(yuǎn)程方法調(diào)用程序一般所需要的幾個(gè)步驟。

第一步:創(chuàng)建共享遠(yuǎn)程對(duì)象

創(chuàng)建一個(gè)C# Library,并將其命名為RemoteObject。這將創(chuàng)建一個(gè)我們的.NET Remote客戶端和服務(wù)器端用來(lái)通訊的“共享命令集”。
public class RemoteObject : System.MarshalByRefObject
{
     public RemoteObject()
     {
        System.Console.WriteLine("New Referance Added!");
     }

     public int sum(int a, int b)
     {
        return a + b;
     }
}
名字空間是對(duì)象所需要的。請(qǐng)記住,如果得到System.Runtime.Remoting.Channels.Tcp名字空間不存在的信息,請(qǐng)檢查是否象上面的代碼那樣添加了對(duì)System.Runtime.Remoting.dll的引用。

using System;
using System.Runtime;

我們?yōu)閷?duì)象使用的名字空間是RemoteSample,下面的對(duì)象是MarshalByRefObject,在其中我們創(chuàng)建了一個(gè)引用和包括服務(wù)器端操作全部完成所需要的所有工作。

namespace RemoteSample
{
public class RemoteObject : System.MarshalByRefObject
{
    public RemoteObject()
    {
       System.Console.WriteLine("New Referance Added!");
    }

    public int sum(int a, int b)
    {
       return a + b;
    }
}
}//RemoteSample名字空間結(jié)束

保存文件,命名為RemoteObject.cs
用命令行csc /t:library RemoteObject.cs 編譯文件,就會(huì)得到一個(gè)RemoteObject.DLL文件,并可以在編譯其他的C#文件中使用它。

第二步:創(chuàng)建服務(wù)器對(duì)象

創(chuàng)建服務(wù)器對(duì)象,并將它命名為RemoteServer。在創(chuàng)建服務(wù)器對(duì)象時(shí)必須實(shí)現(xiàn)以下操作:

1)構(gòu)造服務(wù)器信道。
TcpServerChannel是.NET remoting支持的二種信道類型中的一種,可以將它設(shè)置為對(duì)象對(duì)來(lái)自哪一個(gè)端口的請(qǐng)求進(jìn)行回應(yīng),ChannelServices.RegisterChannel將把該端口號(hào)與
操作系統(tǒng)中的TCP/ip棧綁定。

TcpServerChannel channel = new TcpServerChannel(8808);
ChannelServices.RegisterChannel(channel);

也可以設(shè)置為另一種的信道類型HTTP,只要簡(jiǎn)單地用System.Runtime.Remoting.Channels.Http名字空間中的HttpServerChannel對(duì)象替換即可。使用HTTP和TCP信道之間的區(qū)別在于:如果應(yīng)用程序是在局域網(wǎng)上運(yùn)行,則最好使用TCP信道,因?yàn)樗男阅芤糜贖TTP信道;如果應(yīng)用程序是在互聯(lián)網(wǎng)上運(yùn)行,則有時(shí)候根據(jù)防火墻的配置,HTTP是唯一的選擇。需要記住的是,如果使用了防火墻軟件,則防火墻應(yīng)該配置成允許TCP數(shù)據(jù)流量通過(guò)你為對(duì)象選擇的端口。

2)將服務(wù)端上的對(duì)象 Type 注冊(cè)為已知類型。
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject),
"RemoteObject", WellKnownObjectMode.SingleCall);
這行代碼設(shè)置了服務(wù)中的一些參數(shù)和把欲使用的對(duì)象名字與遠(yuǎn)程對(duì)象進(jìn)行綁定,第一個(gè)參數(shù)是綁定的對(duì)象,第二個(gè)參數(shù)是TCP或HTTP信道中遠(yuǎn)程對(duì)象名字的字符串,第三個(gè)參數(shù)讓容器知道,當(dāng)有對(duì)對(duì)象的請(qǐng)求傳來(lái)時(shí),應(yīng)該如何處理對(duì)象。盡管WellKnownObjectMode.SingleCall對(duì)所有的調(diào)用者使用一個(gè)對(duì)象的實(shí)例,但它為每個(gè)客戶生成這個(gè)對(duì)象的一個(gè)實(shí)例。如果用WellKnownObjectMode.SingleCall則每個(gè)傳入的消息由同一個(gè)對(duì)象實(shí)例提供服務(wù)。

完整的對(duì)象代碼如下所示:
using System; using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemoteSample;
namespace RemoteSampleServer
{
  public class RemoteServer
  {
      public static void Main(String[] args)
      {
         TcpServerChannel channel = new TcpServerChannel(8808);
         ChannelServices.RegisterChannel(channel);
         RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject),
                                  "RemoteObject", WellKnownObjectMode.SingleCall);
         System.Console.WriteLine("Press Any Key");
         System.Console.ReadLine();
       }
   }
}
保存文件,命名為RemoteServer.cs
用命令行csc /r:System.Runtime.Remoting.dll /r:RemoteObject.dll RemoteServer.cs 編譯這一程序生成的RemoteServer.EXE文件。

第三步:創(chuàng)建Remote客戶端程序
創(chuàng)建服務(wù)器對(duì)象,并將它命名為RemoteClient。在創(chuàng)建服務(wù)器對(duì)象時(shí)首先創(chuàng)建了一個(gè)TCP客戶端信道,該信道并不是綁定在一個(gè)端口上的;其次獲取一個(gè)對(duì)遠(yuǎn)程的RemoteObject對(duì)象的引用。 Activator.GetObject方法返回一個(gè)對(duì)象類型的值,我們隨后會(huì)將它返回的值賦予RemoteObject。我們傳給它的參數(shù)與在服務(wù)器對(duì)象中傳遞給RemotingConfiguration的參數(shù)非常地相似,第一個(gè)參數(shù)是對(duì)象類型的,第二個(gè)參數(shù)是遠(yuǎn)程對(duì)象的URI。

ChannelServices.RegisterChannel(new TcpClientChannel());
RemoteObject remoteobj = (RemoteObject)Activator.GetObject( typeof(RemoteObject),
                       "tcp://localhost:8808/RemoteObject");

RemoteClient的全部代碼如下所示:

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemoteSample;
namespace RemoteSampleClient
{
  public class RemoteClient
  {
     public static void Main(string[] args)
     {
        ChannelServices.RegisterChannel(new TcpClientChannel());
        RemoteObject remoteobj = (RemoteObject)Activator.GetObject( typeof(RemoteObject),
                           "tcp://localhost:8808/RemoteObject");
        Console.WriteLine("1 + 2 = " + remoteobj.sum(1,2).ToString());
        Console.ReadLine();//在能夠看到結(jié)果前不讓窗口關(guān)閉
     }

   }
}

保存文件,命名為RemoteClient.cs
用命令行csc /r:System.Runtime.Remoting.dll /r:RemoteObject.dll RemoteClient.cs 編譯這一程序生成的RemoteClient.EXE文件。

第四步:測(cè)試
在windows中運(yùn)行Server.exe,然后打開(kāi)另一個(gè)窗體運(yùn)行Client.exe。
如果一切正常的話,客戶端輸出: 1 + 2 = 3。

由此可見(jiàn),NET Remoting不需要?jiǎng)?chuàng)建存根程序和骨架文件,使用起來(lái)比Java的RMI簡(jiǎn)單,而且為處理局域網(wǎng)甚至互聯(lián)網(wǎng)范圍內(nèi)的資源提供了一個(gè)絕佳的方法,使用范圍比Java的RMI更廣泛。進(jìn)入討論組討論。

(出處:http://m.survivalescaperooms.com)



發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 竹北市| 青阳县| 沭阳县| 大兴区| 灵宝市| 浪卡子县| 神木县| 滦平县| 营山县| 盐城市| 衡南县| 鲜城| 长沙市| 且末县| 泰安市| 鄯善县| 沿河| 黑山县| 新津县| 瑞丽市| 霍州市| 云龙县| 德格县| 东方市| 兴义市| 凌云县| 中西区| 安西县| 凤冈县| 佛山市| 象州县| 太湖县| 天津市| 南和县| 申扎县| 江安县| 格尔木市| 通州市| 泽库县| 达日县| 武城县|