Accueil > Java > Ajouter un timeout en RMI – How to handle a timeout on RMI connections ?

Ajouter un timeout en RMI – How to handle a timeout on RMI connections ?

29/06/2010

Par défaut les connexions RMI ont un timeout assez long (20s sur mon environnement).

Il peut être utile de gérer soit même le timeout utilisé pour se connecter au serveur RMI.

Prenons le code suivant:

Here is a little « How to handle timeout on a RMI connection », lets try the execution of following code:


import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;

/**
 * Exécution:
 *
 * java -Djava.security.policy=policy.txt TestRmi
 *
 * policy.txt
 * -------------------
 * grant {
 *   // Allow everything for now
 *   permission java.security.AllPermission;
 * };
 * -------------------
 */

public class TestRmi {
    public static void main(final String[] args) {
        // Server Side
        try {
            LocateRegistry.createRegistry(1099);
            System.setSecurityManager(new RMISecurityManager());
            Test test = new TestServer();
            Naming.rebind("rmi://localhost:1099/test", test);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        // Client side
        long start = System.currentTimeMillis();
        try {
            //RMISocketFactory.setSocketFactory(new TimedSocketFactory(2000));
            Test test = (Test) Naming.lookup("rmi://128.0.0.1:1099/test");
            System.out.println(test.sayMeHello());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Duration: " + (System.currentTimeMillis() - start));
    }

    private static interface Test extends Remote, Serializable {
        String sayMeHello() throws RemoteException;
    }

    private static class TestServer implements Test {
        /** The serialVersionUID. */
        private static final long serialVersionUID = 5171499581308608043L;

        public String sayMeHello() {
            return "Hello !";
        }
    }
}

Après l’avoir lancé, vous obtiendrez une stack trace puis un temps de l’ordre de 20s. Pour gérer cela, nous allons utiliser notre propre implémentation du RMISocketFactory.

You may have seen that duration variable is up to 20s … Lets implements our TimedSocketFactory :

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;

public class TimedSocketFactory extends RMISocketFactory {
    private final int timeout;

    /**
     * @param timeout The time out in milliseconds.
     */
    public TimedSocketFactory(final int timeout) {
        this.timeout = timeout;
    }

    public Socket createSocket(final String host, final int port) throws IOException {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(host, port), timeout);
        socket.setSoTimeout(timeout);
        socket.setSoLinger(false, 0);
        return socket;
    }

    public ServerSocket createServerSocket(final int port) throws IOException {
        return getDefaultSocketFactory().createServerSocket(port);
    }
}

Décommentez la ligne:

RMISocketFactory.setSocketFactory(new TimeoutSocketFactory(2000));

Et relancez, vous obtiendrez un temps légèrement supérieur à 2s !!

Et voilà le tour est joué !


Uncomment the line:

RMISocketFactory.setSocketFactory(new TimeoutSocketFactory(2000));

Than restart, and you will have duration time arround 2s !!


Java ,

Les commentaires sont fermés.