Чистый способ остановить RMI сервер

1

Сервер RMI, который отлично работает без функции stopServer.

public class HelloServer extends UnicastRemoteObject implements HelloInterface
{
    private final static int PORT=1102;
    private final String serverName="server"; 
    private Timer timer;

    public HelloServer()  throws RemoteException 
    {
       timer = new Timer();  //At this line a new Thread will be created
       timer.schedule(new StopServerTask(), 5000);

    }

    @Override
    public String serverResponse(String request) throws RemoteException 
    {
    return "Hello"+request;
    }


    public static void main(String[] args)
    {

        try 
        {

            HelloServer skeleton=new HelloServer();
            System.out.println("Starting server");
            skeleton.startServer();
            System.out.println("Server started");


        } 
        catch (RemoteException ex) 
        {
            ex.printStackTrace();
        }


    }

    public void startServer()
    {
  try {

            HelloServer skeleton=new HelloServer();
            Registry reg=LocateRegistry.createRegistry(PORT);
            reg.rebind(serverName, skeleton);
            System.out.println("Server is ready");

        } catch (RemoteException ex) 
        {
            Logger.getLogger(HelloInterface.class.getName()).log(Level.SEVERE, null, ex);
        }    
    }

    public void stopServer()
    {
    System.out.println("Stopping server");
        try {

            Registry rmiRegistry = LocateRegistry.getRegistry(PORT);
            HelloInterface myService = (HelloInterface) rmiRegistry.lookup(serverName);

            rmiRegistry.unbind(serverName);

            UnicastRemoteObject.unexportObject(rmiRegistry, true);

        } catch (NoSuchObjectException e) 
        {
            e.printStackTrace();
        } catch (NotBoundException e) 
        {
            e.printStackTrace();
        } catch (RemoteException ex) {
            Logger.getLogger(HelloServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    class StopServerTask extends TimerTask
        {

        @Override
        public void run() 
        {
        stopServer();
        }

        }
}

Всякий раз, когда stopServer() в вызываемом исключении

UnicastRemoteObject.unexportObject(rmiRegistry, true);

Вот трассировка стека

java.rmi.NoSuchObjectException: object not exported
    at sun.rmi.transport.ObjectTable.unexportObject(ObjectTable.java:153)
    at java.rmi.server.UnicastRemoteObject.unexportObject(UnicastRemoteObject.java:297)
    at rmi.HelloServer.stopServer(HelloServer.java:84)

То же самое происходит, когда я очищаю объект службы, используя

 UnicastRemoteObject.unexportObject(myService, true);

Может ли кто-нибудь предложить чистый способ остановить сервер, который также освобождает порт для повторного использования.

Теги:
rmi

2 ответа

1
Лучший ответ

Вам нужно сохранить результат LocateRegistry.createRegistry(), и LocateRegistry.createRegistry(), из LocateRegistry.createRegistry(),. В настоящее время вы пытаетесь развернуть заглушку.

0

На моем rmi-сервере я выполнил shutdown-service. Если я хочу закрыть его, я называю его паролем. Простой пример:

public interface ShutdownInterface extends Remote {
  public void shutdownService(String password) throws RemoteException;
}

Реализация serveride может выглядеть примерно так:

public class ShutdownService extends UnicastRemoteObject implements ShutdownInterface {

private static final long serialVersionUID = 1L;

private boolean doShutdown = false;

public ShutdownService() throws RemoteException {
    super();
}

@Override
public void shutdownService(String password) throws RemoteException {
    if ("abcde12345".equals(password)) {
        System.out.println("shutdown requested.");
        this.doShutdown = true;
    } else {
        System.out.println("wrong pwd for shutdown");
    }

}

public boolean isDoShutdown() {
    return this.doShutdown;
}

}

Теперь сам сервер ссылается на это:

public class BackendServer {
public final static int RMI_PORT = 1974;
private Registry registry = null;
private ShutdownService shutdownService = null;

public BackendServer() throws RemoteException {
    registry = LocateRegistry.createRegistry(RMI_PORT);
    this.shutdownService = new ShutdownService();
}

public void initialize() throws AccessException, RemoteException, AlreadyBoundException {
    shutdownService = new ShutdownService();
    registry.bind("ShutdownService", shutdownService);
    registry.bind("MyDataService", new MyDataService());
}

public void stop() throws NoSuchObjectException {
    System.out.println("stopping rmi server.");
    UnicastRemoteObject.unexportObject(registry, true);
    System.exit(0);
}

public boolean shouldStop() {
    return this.shutdownService.isDoShutdown();
}

public static void main(String args[]) {
    try {
        BackendServer bs = new BackendServer();
        bs.initialize();
        System.out.println("Server ready.");

        while (!bs.shouldStop()) {
            Thread.sleep(1000);
        }
        bs.stop();
    } catch (Exception e) {
        System.err.println("Server exception: " + e.toString());
        e.printStackTrace();
    }
}

}

Конечно, это может быть реализовано более красиво, но это должно дать вам представление о том, как легко реализовать выключение самостоятельно. Вы можете вызвать его от основного клиента или от небольшого инструмента командной строки, который вы кодируете для своего сервера.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню