كيف يمكنني التأكد من أن RMI يستخدم سوى مجموعة محددة من الموانئ

StackOverflow https://stackoverflow.com/questions/56687

  •  09-06-2019
  •  | 
  •  

سؤال

في التطبيق لدينا ، نحن نستخدم RMI على ملقم-عميل الاتصالات بطرق مختلفة جدا:

  1. دفع البيانات من الخادم إلى العميل ليتم عرضها.
  2. إرسال التحكم في المعلومات من العميل إلى الملقم.
  3. رد من تلك رسائل التحكم رمز المسارات التي تصل إلى العودة من الخادم إلى العميل (الشريط الجانبي ملاحظة - هذا هو أحد الآثار الجانبية لبعض التعليمات البرمجية القديمة وليس لدينا على المدى الطويل نية).

ما نود القيام به هو التأكد من أن كل من جمهورية جزر مارشال التعليمات البرمجية ذات الصلة سوف تستخدم فقط معروفة محددة المخزون من الموانئ.ويشمل هذا التسجيل ميناء (عادة من المتوقع أن يكون 1099), منفذ الخادم و أي منافذ الناتجة عن رد.

هنا هو ما نعرفه بالفعل:

  1. LocateRegistry.getRegistry(1099) أو موقع.createRegistry(1099) سوف تضمن أن التسجيل يتم الاستماع في 1099.
  2. باستخدام UnicastRemoteObject منشئ / exportObject أسلوب ثابت مع منفذ الحجة تحديد منفذ الملقم.

هذه النقاط هي أيضا مشمولة في هذا الشمس منتدى آخر.

ما لا نعرفه هو:كيف يمكننا التأكد من أن اتصالات العميل إلى الملقم الناتجة من رد فقط الاتصال على المنفذ المحدد بدلا من التخلف مجهول الميناء ؟

تحرير:وأضاف الكاسح إجابة تلخص النتائج التي توصلت إليها وكيفية حل المشكلة.نأمل أن هذا سوف يساعد أي شخص آخر مع قضايا مماثلة.

تحرير الثاني:اتضح أنه في طلبي ، يبدو أن هناك حالة سباق في إنشاء وتعديل مأخذ المصانع.وقد أردت أن تسمح للمستخدم تجاوز الإعدادات الافتراضية في Beanshell النصي.للأسف, يبدو أن السيناريو يتم تشغيله بشكل كبير بعد أول مأخذ يتم إنشاؤه من قبل المصنع.ونتيجة لذلك أنا الحصول على مزيج من الموانئ من مجموعة من الافتراضات و إعدادات المستخدم.فإنه يلزم مزيد من العمل خارج نطاق هذا السؤال ولكن أعتقد أنه قد أشير إليه كنقطة اهتمام الآخرين الذين قد يكون فقي هذه المياه في بعض نقطة....

هل كانت مفيدة؟

المحلول

يمكنك أن تفعل هذا مع العرف RMI مأخذ المصنع.

مأخذ المصانع إنشاء قواعد RMI أن تستخدم في كل من العميل والخادم نهاية لذلك إذا كنت أكتب الخاصة بك لديك السيطرة الكاملة على المنافذ المستخدمة.العميل المصانع التي تم إنشاؤها على الملقم تسلسل ومن ثم إرسالها إلى العميل الذي هو أنيق جدا.

هنا دليل على الشمس أقول لك كيف تفعل ذلك.

نصائح أخرى

أنت لا تحتاج إلى مأخذ المصانع ، أو حتى منافذ متعددة.إذا كنت تبدأ التسجيل من الخادم الخاص بك JVM يمكنك استخدام ميناء 1099 في كل شيء ، والواقع أن هذا هو ما سيحدث بشكل افتراضي.إذا كنت لا تبدأ التسجيل في كل شيء ، كما في عميل رد كائن ، يمكنك توفير ميناء 1099 عند تصديره.

جزء من سؤالك عن اتصالات العميل إلى الملقم الناتجة عن رد لا معنى له.فهي لا تختلف عن الأصلية اتصالات العميل إلى الخادم ، وأنها سوف تستخدم نفس server port(s).

ملخص الجواب طويلة أدناه:لحل المشكلة التي لدي (تقييد خادم رد الموانئ في نهاية RMI اتصال) كنت بحاجة إلى إنشاء اثنين من أزواج من العميل والخادم مأخذ المصانع.

الإجابة أطول تستتبعه:

لدينا الحل الاستدعاء المشكلة أساسا في ثلاثة أجزاء.كان أول كائن التغليف التي تحتاج إلى القدرة على تحديد أن كانت تستخدم العميل إلى الملقم اتصال مقابلتستخدم الملقم إلى العميل رد.باستخدام امتداد 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));
}
// ....
}

لذا ، فإن أول حجة يحدد الجزء الذي هو كائن أتوقع الطلبات ، بينما الثانية والثالثة تحديد مأخذ المصانع التي سيتم استخدامها في نهاية اتصال يقود هذا الكائن البعيد.

منذ أردنا تقييد المنافذ المستخدمة من قبل الصدد نحن بحاجة إلى تمديد RMI مأخذ المصانع و غلق الموانئ.وهنا بعض الرسومات من الخادم و العميل المصانع:

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);
    }
}
// ....
}

إذن الشيء الوحيد المتبقي إلى اتجاهين اتصال البقاء على نفس مجموعة من الموانئ بعض المنطق أن ندرك أن كنت تتصل مرة أخرى إلى العميل.في هذه الحالة فقط تأكد من أن المصنع الخاص بك طريقة كائن بعيد يدعو RemoteObjectWrapper منشئ الأعلى مع المعلمة رد تعيين إلى true.

لقد كان لديها مشاكل مختلفة تنفيذ RMI الخادم/العميل العمارة مع العميل رد.السيناريو بلدي هو أن كلا من الخادم و العميل وراء جدار الحماية/NAT.في نهاية المطاف حصلت على العمل بشكل كامل التنفيذ.هنا هي الأشياء الرئيسية التي فعلت:

من جانب الملقم المحلي IP:192.168.1.10.العامة (الإنترنت) IP 80.80.80.10

على جدار الحماية/راوتر/Local Server PC فتح منفذ 6620.على جدار الحماية/راوتر/Local Server PC فتح منفذ 1099.على جهاز التوجيه/NAT إعادة توجيه الاتصالات الواردة على المنفذ 6620 إلى 192.168.1.10:6620 على جهاز التوجيه/NAT إعادة توجيه الاتصالات الواردة على المنفذ 1099 إلى 192.168.1.10:1099

في البرنامج الفعلي:

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);

جانب العميل, IP المحلي:10.0.1.123 العامة (الإنترنت) IP 70.70.70.20

على جدار الحماية/راوتر/Local Server PC فتح منفذ عام 1999.على جهاز التوجيه/NAT إعادة توجيه الاتصالات الواردة على المنفذ 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 ");

ويساعد هذا الأمل.Iraklis

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top