#java #sockets #singleton #ipc #serversocket
#java #сокеты #singleton #ipc #serversocket
Вопрос:
Я пытаюсь создать программу на Java, в которой одновременно может быть запущен только один ее экземпляр. Я использую сокеты и ServerSockets, чтобы попытаться достичь этого.
Предполагается, что программа должна работать следующим образом:
Метод main проверит, были ли переданы какие-либо параметры, он попытается записать первый параметр на сервер, если это не удастся, это означает, что это единственный запущенный экземпляр, поэтому он откроет ServerSocket и затем запустит фрейм. Если он не завершается сбоем, то приложение уже запущено, поэтому оно должно отправить строку, а другой экземпляр должен иметь возможность ее прочитать и обработать.
Вот основной метод:
public static void main(String[] args) {
String fileName = null;
if (args.length >= 1) {
fileName = args[0];
}
if (Singleton.sendSignal(fileName)) {
Frame.getFrame().open(fileName);
Singleton.checkInput();
}
}
И вот класс сервера:
public class Singleton {
private static final int portNumber = 4243;
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static Socket echoSocket;
public static boolean sendSignal() {
try {
echoSocket = new Socket(InetAddress.getLocalHost().getHostName(), portNumber);
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
out.write("Openn");
out.close();
close();
return false;
} catch (Exception e) {
close();
return true;
}
}
public static void checkInput() {
try {
renewReader();
} catch (Exception e) {
close();
}
}
public static void renewReader() throws Exception {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = in.readLine();
if (inputLine.equals("Open")) {
Widget.getInstance().setVisible(true);
}
close();
renewReader();
}
public static void close() {
try {
serverSocket.close();
} catch (Exception e) {
}
try {
clientSocket.close();
} catch (Exception e) {
}
try {
echoSocket.close();
} catch (Exception e) {
}
}
}
Хотя половина этого кода работает (одновременно выполняется только один экземпляр), передается только первый набор данных, а затем программа прекращает чтение. Как я могу заставить сокет прослушивать, пока программа не будет закрыта?
Ответ №1:
В вашем методе checkInput() вы принимаете подключение к клиенту один раз здесь. Попробуйте что-то вроде этого:
public static void checkInput()
{
//do something here
serverSocket = new ServerSocket(portNumber);
//wait for request from client.
Socket clientSocket = serverSocket.accept();
//
// do your processing here
// call checkInput method again.
checkInput();
}
Как только запустится другой экземпляр, сервер примет запрос, выполнит обработку, а затем снова начнет ждать дополнительных запросов (для этого мы снова вызвали cehckInput).
Также в вашем main() добавьте это:
public static void main(String[] args)
{
String fileName = null;
if (args.length >= 1) {
fileName = args[0];
}
if (Singleton.sendSignal(fileName))
{
Frame.getFrame().open(fileName);
// start the server in a thread so that main method can continue on
new Thread()
{
public void run()
{
Singleton.checkInput();
}
}.start();
}
// do your other tasks.
}
При завершении программы ваши сокеты автоматически закроются. Также, если вы хотите явно закрыть сокеты, вы можете добавить перехват завершения работы, чтобы закрыть его.
Простой хук выглядит следующим образом.
Runtime.getRuntime().addShutdownHook(your thread that will close sockets);
Комментарии:
1. необходим ли новый поток? программа отлично работает без дополнительного. Я имею в виду, что ничего не приостановлено.
2. Я добавил thread на всякий случай, так как если вы добавите какой-либо новый код в свой метод main() после условия if, он не будет выполняться, поскольку метод checkInput() вызывается рекурсивно. Таким образом, было бы разумно на всякий случай добавить рекурсивный метод в поток. И да, вы можете игнорировать часть потока, если вы уверены, что после этого в main больше не будет строк кода.