java मतलब मैं कैसे सुनिश्चित करूं कि आरएमआई केवल एक विशिष्ट बंदरगाहों का उपयोग करता है?




हल्दिया बंदरगाह (4)

आप इसे कस्टम आरएमआई सॉकेट फैक्टरी के साथ कर सकते हैं।

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

यहां सूर्य की एक मार्गदर्शिका है जो आपको बता रही है कि यह कैसे करना है।

हमारे आवेदन में, हम बहुत अलग तरीके से क्लाइंट-सर्वर संचार के लिए आरएमआई का उपयोग कर रहे हैं:

  1. प्रदर्शित करने के लिए ग्राहक से सर्वर से डेटा धक्का।
  2. क्लाइंट से सर्वर पर नियंत्रण जानकारी भेजना
  3. उन नियंत्रण संदेश कोड पथों से कॉलबैक जो सर्वर से ग्राहक तक वापस पहुंचते हैं (साइडबार नोट - यह कुछ विरासत कोड का एक साइड-प्रभाव है और हमारा दीर्घकालिक इरादा नहीं है)।

हम क्या करना चाहते हैं यह सुनिश्चित करना है कि हमारे सभी आरएमआई संबंधित कोड केवल एक ज्ञात निर्दिष्ट बंदरगाहों का उपयोग करेगा। इसमें रजिस्ट्री पोर्ट (आमतौर पर 10 99 होने की उम्मीद है), सर्वर बंदरगाह और कॉलबैक से उत्पन्न किसी भी बंदरगाह शामिल हैं।

यहाँ हम पहले से ही जानते हैं:

  1. LocateRegistry.getRegistry (10 99) या Locate.createRegistry (1099) यह सुनिश्चित करेगा कि रजिस्ट्री 10 99 पर सुन रही है।
  2. UnicastRemoteObject कन्स्ट्रक्टर / निर्यात ऑब्जेक्ट स्टैटिक विधि का प्रयोग पोर्ट पोर्ट के साथ करेगा, सर्वर पोर्ट निर्दिष्ट करेगा

इन बिंदुओं को भी इस सूर्य मंच पोस्ट में शामिल किया गया है।

हमें क्या पता नहीं है: हम कैसे सुनिश्चित करते हैं कि क्लाइंट कनेक्शंस कॉलबैक से आने वाले सर्वर को वापस केवल एक निर्दिष्ट बंदरगाह पर ही गुम हो जाए, जो कि किसी गुमनाम बंदरगाह को चूकने की बजाय?

संपादित करें: मेरे निष्कर्षों को सारांशित करने के लिए एक लंबा जवाब दिया गया और हमने समस्या का समाधान कैसे किया। उम्मीद है, यह इसी तरह के मुद्दों के साथ किसी और को मदद करेगा।

दूसरा संपादन: यह पता चला है कि मेरे आवेदन में, मेरी सृजन और सॉकेट फैक्ट्रियों के संशोधन में एक दौड़ की स्थिति होती है। मैं उपयोगकर्ता को अपने डिफ़ॉल्ट सेटिंग्स को एक बेन्सल स्क्रिप्ट में ओवरराइड करने की अनुमति देना चाहता था। अफसोस की बात है, ऐसा प्रतीत होता है कि कारखाने द्वारा पहली सॉकेट बनाने के बाद मेरी स्क्रिप्ट काफी चल रही है। नतीजतन, मुझे डिफ़ॉल्ट सेट और उपयोगकर्ता सेटिंग से बंदरगाहों का मिश्रण मिल रहा है अधिक काम की आवश्यकता होगी जो कि इस प्रश्न के दायरे से बाहर है लेकिन मैंने सोचा था कि मैं इसे उन लोगों के लिए ब्याज की एक बिंदु के रूप में समझा दूंगा, जो किसी बिंदु पर इन जल को चलाना पड़ सकता है ....


लंबे समय से उत्तर का सारांश: मुझे जो समस्या थी (आरआईआई कनेक्शन के दोनों ओर सर्वर और कॉलबैक बंदरगाहों को प्रतिबंधित करने) को हल करने के लिए, मुझे क्लाइंट और सर्वर सॉकेट कारखानों के दो जोड़े बनाने की जरूरत थी।

लंबे समय के उत्तर में आता है:

कॉलबैक समस्या का हमारा समाधान अनिवार्य रूप से तीन भागों था। पहला ऑब्जेक्ट रैपिंग था, जिसने यह निर्दिष्ट करने की क्षमता की आवश्यकता थी कि क्लाइंट के लिए क्लाइंट कॉलबैक के लिए सर्वर कनेक्शन बनाम इस्तेमाल किया जा रहा है। UnicastRemoteObject एक विस्तार का उपयोग करने से हमें क्लाइंट और सर्वर सॉकेट कारखानों को निर्दिष्ट करने की क्षमता मिल गई, जो हम उपयोग करना चाहते थे। हालांकि, सॉकेट कारखानों को लॉक करने के लिए सबसे अच्छी जगह रिमोट ऑब्जेक्ट के कन्स्ट्रक्टर में है।

public class RemoteObjectWrapped extends UnicastRemoteObject {
// ....
private RemoteObjectWrapped(final boolean callback) throws RemoteException {
  super((callback ? RemoteConnectionParameters.getCallbackPort() : RemoteConnectionParameters.getServerSidePort()),
        (callback ? CALLBACK_CLIENT_SOCKET_FACTORY : CLIENT_SOCKET_FACTORY),
        (callback ? CALLBACK_SERVER_SOCKET_FACTORY : SERVER_SOCKET_FACTORY));
}
// ....
}

इसलिए, पहला तर्क उस भाग को निर्दिष्ट करता है जिस पर ऑब्जेक्ट अनुरोधों की अपेक्षा कर रहा है, जबकि दूसरा और तीसरा सॉकेट कारखानों को निर्दिष्ट करता है जो कनेक्शन के अंत में इस रिमोट ऑब्जेक्ट को चलाएगा।

चूंकि हम कनेक्शन द्वारा इस्तेमाल किए गए बंदरगाहों को प्रतिबंधित करना चाहते थे, इसलिए हमें आरएमआई सॉकेट कारखानों का विस्तार करना और बंदरगाहों को बंद करना आवश्यक था। हमारे सर्वर और ग्राहक कारखानों के कुछ स्केच यहां दिए गए हैं:

public class SpecifiedServerSocketFactory implements RMIServerSocketFactory {
/** Always use this port when specified. */
private int serverPort;
/**
 * @param ignoredPort This port is ignored.  
 * @return a {@link ServerSocket} if we managed to create one on the correct port.
 * @throws java.io.IOException
 */
@Override
public ServerSocket createServerSocket(final int ignoredPort) throws IOException {
    try {
        final ServerSocket serverSocket = new ServerSocket(this.serverPort);
        return serverSocket;
    } catch (IOException ioe) {
        throw new IOException("Failed to open server socket on port " + serverPort, ioe);
    }
}
// ....
}

ध्यान दें कि सर्वर सॉकेट फैक्टरी ऊपर यह सुनिश्चित करता है कि केवल आपके द्वारा निर्दिष्ट पोर्ट केवल इस फैक्टरी द्वारा उपयोग किया जाएगा। क्लाइंट सॉकेट फैक्टरी को उचित सॉकेट फैक्ट्री के साथ जोड़ा जाना चाहिए (या आप कभी भी कनेक्ट नहीं होंगे)।

public class SpecifiedClientSocketFactory implements RMIClientSocketFactory, Serializable {
/** Serialization hint */
public static final long serialVersionUID = 1L;
/** This is the remote port to which we will always connect. */
private int remotePort;
/** Storing the host just for reference. */
private String remoteHost = "HOST NOT YET SET";
// ....
/**
 * @param host The host to which we are trying to connect
 * @param ignoredPort This port is ignored.  
 * @return A new Socket if we managed to create one to the host.
 * @throws java.io.IOException
 */
@Override
public Socket createSocket(final String host, final int ignoredPort) throws IOException {
    try {
        final Socket socket = new Socket(host, remotePort);
        this.remoteHost = host;
        return socket;
    } catch (IOException ioe) {
        throw new IOException("Failed to open a socket back to host " + host + " on port " + remotePort, ioe);
    }
}
// ....
}

इसलिए, बंदरगाहों के एक ही सेट पर रहने के लिए अपने दो तरह से कनेक्शन को मजबूर करने के लिए केवल एक चीज यह है कि आप क्लाइंट-साइड पर वापस कॉल कर रहे हैं यह पहचानने के लिए कुछ तर्क है उस स्थिति में, बस सुनिश्चित करें कि रिमोट ऑब्जेक्ट के लिए आपका कारखाना तरीका रिमोट ऑब्जेक्टड्राफर कन्स्ट्रक्टर को कॉलबैक पैरामीटर के साथ सही पर सेट करता है।


क्लाइंट कॉलबैक के साथ, मैं एक आरएमआई सर्वर / क्लाइंट आर्किटेक्चर को लागू करने में विभिन्न समस्याओं का सामना कर रहा हूं। मेरा परिदृश्य यह है कि सर्वर और क्लाइंट दोनों फ़ायरवॉल / NAT के पीछे हैं अंत में मुझे पूरी तरह से कार्यरत कार्यान्वयन मिला। यहाँ उन मुख्य चीजें हैं जिन्हें मैंने किया था:

सर्वर साइड, लोकल आईपी: 192.168.1.10 सार्वजनिक (इंटरनेट) आईपी 80.80.80.10

फ़ायरवॉल / राउटर / लोकल सर्वर पीसी ओपन पोर्ट 6620 पर। फ़ायरवॉल / राउटर / स्थानीय सर्वर पीसी ओपन पोर्ट 10 99 पर। राउटर / एनएटी पर पोर्ट 6620 से 1 9 .2.168.1.10:6620 पर आने वाले कनेक्शन का पुनर्निर्देशन राउटर / एनएटी पर आने वाली रीडायरेक्ट बंदरगाह 1099 से 1 9 .68.1.10:10 99 पर कनेक्शन

वास्तविक कार्यक्रम में:

System.getProperties().put("java.rmi.server.hostname", IP 80.80.80.10);
MyService rmiserver = new MyService();
MyService stub = (MyService) UnicastRemoteObject.exportObject(rmiserver, 6620);
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("FAManagerService", stub);

क्लाइंट साइड, लोकल आईपी: 10.0.1.123 पब्लिक (इंटरनेट) आईपी 70.70.70.20

फ़ायरवॉल / राउटर / स्थानीय सर्वर पीसी ओपन पोर्ट 1999 पर। रूटर / एनएटी पर पोर्ट 1999 से 10.0.1.123.1999 पर आने वाले कनेक्शन का पुनर्निर्देशन

वास्तविक कार्यक्रम में:

System.getProperties().put("java.rmi.server.hostname", 70.70.70.20);
UnicastRemoteObject.exportObject(this, 1999);
MyService server = (MyService) Naming.lookup("rmi://" + serverIP + "/MyService ");

उम्मीद है की यह मदद करेगा। इराक्लिस


आपको इसके लिए गर्तिका कारखानों की आवश्यकता नहीं है, या यहां तक ​​कि कई पोर्ट भी। यदि आप अपने सर्वर JVM से रजिस्ट्री शुरू कर रहे हैं तो आप सब कुछ के लिए पोर्ट 1099 का उपयोग कर सकते हैं, और वास्तव में यह डिफ़ॉल्ट रूप से क्या होगा। अगर आप रजिस्ट्री को बिल्कुल भी शुरू नहीं कर रहे हैं, जैसा कि क्लाइंट कॉलबैक ऑब्जेक्ट में है, तो आप इसे निर्यात करते समय पोर्ट 1099 प्रदान कर सकते हैं।

'क्लाइंट कनेक्शन वापस कॉलबैक के परिणामस्वरूप सर्वर पर' के बारे में आपके प्रश्न का एक हिस्सा मतलब नहीं है वे मूल क्लाइंट कनेक्शन से सर्वर पर अलग नहीं हैं, और वे उसी सर्वर पोर्ट (एस) का उपयोग करेंगे





rmi