java 如果启动了较新的示例,则终止程序的较旧示例

new9mtju  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(138)

场景:一个程序启动一个服务器并侦听另一个程序连接到该服务器;如果另一个程序连接,则关闭旧程序上的服务器,并在新程序上启动相同的服务器,然后重复该循环。
第一次运行程序后,我得到:

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

第二个程序没有等待第一个程序侦听服务器从端口解除绑定,我不知道如何修复它。

vfh0ocws

vfh0ocws1#

主要问题是startServer方法中的逻辑应该在无限循环中运行,以说明套接字可能随时断开连接的脆弱性,更重要的是,对于尝试连接到由处于关闭过程中的前一个示例绑定的端口的场景。

while (true) 
            runServer(port);

其他问题包括当问题出现时关闭资源,以及将来自客户机Socket的异常从来自ServerSocket的异常中嵌套出去;使得无论何时为X1 M3 N1 X抛出异常都不被解释为将结束X1 M4 N1 X方法的执行的异常。

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

Complete code on GitHub

相关问题