Завершение старого экземпляра программы, если запущен более новый экземпляр - PullRequest
1 голос
/ 21 мая 2019

Сценарий: программа запускает сервер и ожидает подключения другой программы к указанному серверу;если подключается другая программа, убейте сервер в старой программе и запустите тот же сервер в новой программе и повторите цикл.

После первого запуска программы я получаю:

thread started
attempting connection
server started

Затем, после повторного запуска программы, первый экземпляр читает:

thread started
attempting connection
server started
Another instance was started, this instance has been shut down
Exception in thread "Thread-0" java.lang.NullPointerException
    at me.aj.phoenix.util.JustOneServer.startServer(JustOneServer.java:37)
    at me.aj.phoenix.util.JustOneServer.run(JustOneServer.java:28)

, а второй экземпляр читает:

attempting connection
Another instance was running and has been closed.
server started
java.net.BindException: Address already in use: NET_Bind
    at java.base/java.net.PlainSocketImpl.bind0(Native Method)
    at java.base/java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:132)
    at java.base/java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:436)
    at java.base/java.net.ServerSocket.bind(ServerSocket.java:381)
    at java.base/java.net.ServerSocket.<init>(ServerSocket.java:243)
    at java.base/java.net.ServerSocket.<init>(ServerSocket.java:187)
    at me.aj.phoenix.util.JustOneServer.startServer(JustOneServer.java:34)
    at me.aj.phoenix.util.JustOneServer.run(JustOneServer.java:26)

По сути, я пытаюсь делать, когдановая версия программы запущена, закройте старую программу и запустите прослушиватель для новой программы

Вот код:

public class TestProgram extends Thread {
    public final int port = 9665;
    ServerSocket serverSocket = null;
    Socket clientSocket = null;

    @Override
    public void run() {
        System.out.println("thread started");
        try {
            this.check();
            this.startServer();
        } catch (IOException ioe) {
            this.startServer();
        }
    }
    public void startServer() {
        try {
            System.out.println("server started");
            serverSocket = new ServerSocket(port, 1);
            clientSocket = serverSocket.accept();
            Logger.print("Another instance was started, this instance has been shut down");
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void check() throws UnknownHostException, IOException {
        System.out.println("attempting connection");
        Socket socket = new Socket("localhost", port);
        if(socket.isConnected()) {
            Logger.print("Another instance was running and has been closed.");
        }
    }
}

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

1 Ответ

0 голосов
/ 22 мая 2019

Основная проблема заключается в том, что логика в методе startServer должна выполняться в бесконечном цикле для учета слабой природы сокетов, которые могут быть отключены в любое время, и, что более важно, для сценария, в котором пытается подключиться к порт, который связан с предыдущим экземпляром, который находится в процессе выключения.

        while (true) 
            runServer(port);

Другие проблемы включают закрытие ресурсов при возникновении проблем и вложение исключений, которые возникают у клиента Socket, из тех, которые происходят из ServerSocket; так что всякий раз, когда выдается исключение для ServerSocket, не интерпретируется как исключение, которое приведет к завершению выполнения метода startServer.

    void runServer(int port) {
        try (ServerSocket serverSocket = new ServerSocket(port, 1)) {
            logger.debug("Server started!");
            try (Socket clientSocket = serverSocket.accept()) {
                logger.debug("Signal to shutdown received. Shutting down.");
                System.exit(0);
            }
        } catch (IOException e) {
            logger.debug("The other application is still shutting down...");
        }
    }

Ниже приведен полный рабочий пример этого:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServerReplacer {

    private static Logger logger = LoggerFactory.getLogger(ServerReplacer.class);

    public static void runReplacerService(int port) {
        searchOlderInstances(port);

        logger.debug("Server starting...");
        while (true) 
            runServer(port);
    }

    private static void searchOlderInstances(int port) {
        logger.debug("Attempting to find older instance...");
        try (Socket socket = new Socket("127.0.0.1", port)) {
            logOtherInstanceFound(socket.isConnected());
        } catch (Exception e) {
            logOtherInstanceFound(false);
        }
    }

    private static void logOtherInstanceFound(boolean otherInstanceFound) {
        logger.debug(otherInstanceFound ? 
            "FOUND ANOTHER INSTANCE RUNNING! It has been signaled to shut down." : 
            "No older instance found.");
    }

    private static void runServer(int port) {
        try (ServerSocket serverSocket = new ServerSocket(port, 1)) {
            logger.debug("Server started!");
            try (Socket clientSocket = serverSocket.accept()) {
                logger.debug("Signal to shutdown received. Shutting down.");
                System.exit(0);
            }
        } catch (IOException e) {
            logger.debug("The other application is still shutting down...");
        }
    }

    public static void main(String[] args) {
        runReplacerService(9665);
    }
}

Надеюсь, это поможет.

...