2011-08-16 16 views
7

मैं आरएमआई के साथ अपना पहला कदम कर रहा हूं, और मेरे पास एक साधारण सवाल है।क्या मुझे काम करने के लिए आरएमआई के लिए क्लाइंट, सर्वर और रजिस्ट्री पर सभी कक्षाओं की आवश्यकता है?

मेरे पास एक .jar फ़ाइल है जिसमें लाइब्रेरी से कई विधियों का कार्यान्वयन है। मैं आरएमआई का उपयोग कर .jar फ़ाइल में इस विधियों को कॉल करना चाहता हूं।

मैं जो कोशिश कर रहा हूं वह ऐसा करने के लिए रैपर का एक प्रकार बनाना है।

तो, मैं कुछ इस तरह पर काम कर रहा हूँ:

इंटरफ़ेस वर्ग: इस इंटरफ़ेस तरीकों दूरस्थ वस्तु द्वारा कार्यान्वित किया जाना है।

कार्यान्वयन वर्ग: इस वर्ग में इंटरफ़ेस विधियों का कार्यान्वयन है, प्रत्येक कार्यान्वयन .jar फ़ाइल में संबंधित विधि को कॉल करता है। उदाहरण के लिए, जार फ़ाइल में getDetails() नामक एक विधि है, और यह "ResponseDetail" ऑब्जेक्ट देता है। ResponseDetail एक प्रतिक्रिया वर्ग है जो मेरे पास .jar में है।

सर्वर वर्ग: यह rmiregistry

ग्राहक वर्ग तरीके बांधता है: यह तरीकों कार्यान्वयन में लागू की खपत होगी।

अभी तक इतना अच्छा है? :)

अब, मेरे पास एक lib फ़ोल्डर है जहां .jar फ़ाइल रहता है।

सर्वर मशीन में मैंने इंटरफ़ेस, कार्यान्वयन और सर्वर कक्षाएं तैनात की हैं। मैंने स्टब उत्पन्न किया है, और मैंने सफलतापूर्वक rmiregistry चलाया, लेकिन, इन विवरणों के साथ:

rmiregistry शुरू करने के लिए, मुझे .jar फ़ाइलों का संदर्भ देने के लिए कमांड लाइन में क्लासपाथ सेट करना पड़ा, अन्यथा मुझे java.lang.NoClassDefFoundError। मैं इस .sh फ़ाइल के साथ यह किया:

THE_CLASSPATH= 
for i in `ls ./lib/*.jar` 
do 
    THE_CLASSPATH=${THE_CLASSPATH}:${i} 
done 

rmiregistry -J-classpath -J".:${THE_CLASSPATH}" 

सर्वर प्रारंभ करने के लिए, मैं .jar फ़ाइलें संदर्भ के लिए classpath सेट करने के लिए भी था, नहीं तो, मैं java.lang.NoClassDefFoundError मिलता है। मैं कुछ इस तरह उपयोग किया है:

THE_CLASSPATH= 
for i in `ls ./lib/*.jar` do 
    THE_CLASSPATH=${THE_CLASSPATH}:${i} 
done 

java -classpath ".:${THE_CLASSPATH}" Server 

क्लाइंट मशीन: क्लाइंट मशीन से Client.class फ़ाइल को चलाने के लिए, मैं यह करने के लिए .jar फ़ाइलों की प्रतिलिपि, और में उन के संदर्भ करना था क्लासपाथ, क्योंकि अन्यथा, यह नहीं चलता है और मुझे java.lang.N.NoClassDefFoundError मिलता है।

THE_CLASSPATH= 
for i in `ls ./lib/*.jar` 
do 
    THE_CLASSPATH=${THE_CLASSPATH}:${i} 
done 

java -classpath ".:${THE_CLASSPATH}" HelloClient 

यह ठीक है: मैं क्लाइंट मशीन पर इस का इस्तेमाल किया था? मेरा मतलब है, क्या मुझे आरएमआई के माध्यम से विधियों को निष्पादित करने के लिए .jar फ़ाइलों को क्लाइंट मशीन पर कॉपी करना है?

+0

स्टैक ओवरफ़्लो में आपका स्वागत है! मैंने आपकी समस्या को आपकी समस्या के बारे में थोड़ा अधिक संकेत देने के लिए बदल दिया, और आपकी पोस्ट को थोड़ा सुधार भी किया। कृपया जांचें कि मैंने आपके अर्थ के कुछ भी नष्ट नहीं किया है। –

उत्तर

3

आपको स्टब्स उत्पन्न नहीं करना चाहिए (यदि आप एक ट्यूटोरियल का पालन कर रहे हैं, तो यह रास्ता पुराना है)।आप क्लाइंट को स्थानीय रूप से जार स्थानीय रूप से (रिमोट क्लासलोडिंग का उपयोग करके) चलाने के बिना चला सकते हैं, लेकिन यह रास्ता स्थानीय रूप से उपलब्ध जार के साथ ऐसा करने में आसान है (मैंने व्यक्तिगत रूप से आरएमआई का एक उचित हिस्सा किया है और वास्तव में कभी तैनात नहीं किया है रिमोट क्लासलोडिंग के साथ सिस्टम)। आम तौर पर, आप 2 जार, बस दूरदराज के इंटरफेस (और किसी भी Serializable उन इंटरफेस द्वारा इस्तेमाल किया वर्ग) के साथ एक "ग्राहक" जार और एक "सर्वर" जार जो कार्यान्वयन वर्ग शामिल करना चाहते हैं। फिर आप सर्वर जार के साथ सर्वर चलाएंगे, और क्लाइंट जार के साथ rmiregistry/क्लाइंट चलाएंगे।

यह एक बहुत अच्छी (तारीख और सरल तक) getting started guide

+0

धन्यवाद jtalhborn! मैं उस गाइड को आज़मा दूंगा और आपको बता दूंगा कि यह कैसे चला गया। –

+0

हाय jtalhborn! मैंने उस नमूने की कोशिश की है, लेकिन मैं इसे रिमोट क्लाइंट मशीन से नहीं चला सकता :(, और इसमें कोई अतिरिक्त जार फाइल शामिल नहीं है। मैं कोशिश करता रहूंगा, लेकिन वैसे भी धन्यवाद। –

+0

क्या काम नहीं कर रहा है? – jtahlborn

6

जेडीके v5 से पहले किसी को rmic ( आरएमआई कंपाइलर) का उपयोग करके आरएमआई स्टब उत्पन्न करना पड़ा था। यह स्वचालित रूप से जेडीके v5 से किया जाता है। इसके अलावा, आप जावा कोड के भीतर से आरएमआई रजिस्ट्री भी शुरू कर सकते हैं। एक सरल RMI आवेदन के साथ शुरू करने के लिए आप निम्न चरणों का पालन करना चाहते हो सकता है:


import java.rmi.*; 
import java.rmi.server.*; 
public class SomeImpl extends UnicastRemoteObject implements SomeInterface { 
    public SomeImpl() throws RemoteException { 
    super(); 
    } 
    public String someMethod1() throws RemoteException { 
    return "Hello World!"; 
    } 
    public int someMethod2(float f) throws RemoteException { 
    return (int)f + 1; 
    } 
    public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException { 
    int i = someStruct.getInt(); 
    float f = someStruct.getFloat(); 
    someStruct.setInt(i + 1); 
    someStruct.setFloat(f + 1.0F); 
    return someStruct; 
    } 
} 
  • एक को लागू करें:
    
    import java.rmi.*; 
    public interface SomeInterface extends Remote { 
        public String someMethod1() throws RemoteException; 
        public int someMethod2(float someParameter) throws RemoteException; 
        public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException; 
    } 
    
  • इंटरफ़ेस को लागू:

    1. इंटरफ़ेस बनाएँ गैर आदिम serializable वस्तु है कि एक क्लाइंट और सर्वर के बीच भेजा जाता: 0,123,585
      
      import java.io.*; 
      import java.rmi.*; 
      import java.rmi.registry.Registry; 
      import java.rmi.registry.LocateRegistry; 
      public class SomeClient { 
          public static void main(String args[]) { 
          try { 
           String hostName; 
           String portNum = "1234"; 
           String registryURL = "rmi://localhost:" + portNum + "/some"; 
           SomeInterface h = (SomeInterface)Naming.lookup(registryURL); 
           // invoke the remote method(s) 
           String message = h.someMethod1(); 
           System.out.println(message); 
           int i = h.someMethod2(12344); 
           System.out.println(i); 
           SomeStruct someStructOut = new SomeStruct(10, 100.0F); 
           SomeStruct someStructIn = new SomeStruct(0, 0.0F); 
           someStructIn = h.someStructTest(someStructOut); 
           System.out.println(someStructIn.getInt()); 
           System.out.println(someStructIn.getFloat()); 
          } catch (Exception ex) { 
           ex.printStackTrace(); 
          } 
          } 
      } 
      

    एक बड़ा क्लाइंट-सर्वर आवेदन तीन मॉड्यूल में विभाजित किया जाना चाहिए::

    
    import java.rmi.*; 
    import java.rmi.server.*; 
    import java.rmi.registry.Registry; 
    import java.rmi.registry.LocateRegistry; 
    import java.net.*; 
    import java.io.*; 
    public class SomeServer { 
        public static void main(String args[]) { 
        String portNum = "1234", registryURL; 
        try{ 
         SomeImpl exportedObj = new SomeImpl(); 
         startRegistry(Integer.parseInt(portNum)); 
         // register the object under the name "some" 
         registryURL = "rmi://localhost:" + portNum + "/some"; 
         Naming.rebind(registryURL, exportedObj); 
         System.out.println("Some Server ready."); 
        } catch (Exception re) { 
         System.out.println("Exception in SomeServer.main: " + re); 
        } 
        } 
        // This method starts a RMI registry on the local host, if it 
        // does not already exist at the specified port number. 
        private static void startRegistry(int rmiPortNum) throws RemoteException{ 
        try { 
         Registry registry = LocateRegistry.getRegistry(rmiPortNum); 
         registry.list(); 
         // The above call will throw an exception 
         // if the registry does not already exist 
        } catch (RemoteException ex) { 
         // No valid registry at that port. 
         System.out.println("RMI registry is not located at port " + rmiPortNum); 
         Registry registry = LocateRegistry.createRegistry(rmiPortNum); 
         System.out.println("RMI registry created at port " + rmiPortNum); 
        } 
        } 
    } 
    
  • ग्राहक को लागू करें:
  • सर्वर लागू client, server, और common (सर्वर और क्लाइंट कोड के बीच साझा कक्षाओं के लिए, यानी रिमोट इंटीरियर इस उदाहरण में राफेस और गैर-आदिम वस्तु)। क्लाइंट अनुप्रयोग तो classpath और classpath पर server + common मॉड्यूल से सर्वर पर client + common मॉड्यूल से बनाया जाएगा।

    मैं कई साल पहले इस उदाहरण का इस्तेमाल किया RMI की मूल बातें जानने के लिए और यह अभी भी काम करता है। हालांकि यह सही होने से बहुत दूर है (डिफ़ॉल्ट जावा पैकेज का उपयोग किया गया है, गलत अपवाद हैंडलिंग, होस्टनाम और पोर्ट पैरामीटर हार्ड-कोडेड हैं और कॉन्फ़िगर करने योग्य नहीं हैं)

    फिर भी, यह शुरुआत करने वालों के लिए अच्छा है। सभी फ़ाइलें एक निर्देशिका में रखा जाता है और सरल javac *.java आदेश का उपयोग कर संकलित किया जा सकता। सर्वर अनुप्रयोग तो java SomeClient आदेश के लॉन्च के साथ java SomeServer और ग्राहक का उपयोग करना प्रारंभ किया जा सकता है।

    मुझे आशा है कि यह जावा RMI जो वास्तव में है, सिर्फ इस की तुलना में कहीं अधिक जटिल को समझने के लिए मदद करता है।

  • +0

    वाह, धन्यवाद जिरी, मैं आपका उदाहरण आज़माउंगा, यह मुझे जो चाहिए उसे बहुत करीब दिखता है। फिर मैं आपको बता दूंगा कि यह शब्द है या नहीं। –

    +0

    अच्छा उदाहरण, जावा 8, thx के साथ भी काम करता है! – Chris

    1

    संक्षेप में यह कहना कि क्या अन्य उत्तर सविस्तार:

    • ग्राहक केवल आम इंटरफेस (और ग्राहक वर्ग), नहीं सर्वर कार्यान्वयन की जरूरत है।

    • सर्वर को इंटरफेस और कार्यान्वयन (और आपके सर्वर मुख्य वर्ग) की आवश्यकता है।

    • rmiregistry केवल इंटरफ़ेस की आवश्यकता है।

      (वास्तव में, आप अपने खुद रजिस्ट्री सर्वर प्रक्रिया के अंदर शुरू कर सकते हैं - तो आप rmiregistry बिल्कुल जरूरत नहीं है java.rmi.registry.LocateRegistry कक्षा में createRegistry तरीकों पर एक नजर डालें।।)

    " इंटरफ़ेस "का अर्थ है रिमोट इंटरफेस और किसी भी (धारावाहिक) कक्षाओं को पैरामीटर या तर्क प्रकार के रूप में उपयोग किया जाता है।

    आप इन कक्षाओं को जार फ़ाइलों में कैसे वितरित करते हैं, इससे स्वतंत्र है।

    +0

    धन्यवाद Paŭlo ! अपने बिंदुओं के बारे में, यदि पहला सत्य है: क्लाइंट को केवल सामान्य इंटरफेस (और क्लाइंट क्लासेस) की आवश्यकता होती है, न कि सर्वर कार्यान्वयन। तो मैं कुछ गलत कर रहा हूं, क्योंकि मेरे पास .jar फाइलें हैं क्लाइंट कॉल चलाने के लिए। मैं ऊपर दिए गए उदाहरणों का प्रयास करूंगा और देख सकता हूं कि यह कैसे काम करता है। –

    संबंधित मुद्दे

     संबंधित मुद्दे