Note that there are some explanatory texts on larger screens.

plurals
  1. POJava single instance software with socket. issue in closing socket under windows
    primarykey
    data
    text
    <p>I need to force my Java application to run with a single instance. I found on <a href="http://www.rbgrn.net/content/43-java-single-application-instance" rel="nofollow noreferrer">this link</a> this very nice piece of code that solve the problem using socket instead of using the file system.</p> <p>here the as i adjusted:</p> <p>package cern.ieplc.controller; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException;</p> <p>import org.apache.log4j.Logger;</p> <p>import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream;</p> <pre><code>public class ApplicationInstanceManager { public interface ApplicationInstanceListener { public void newInstanceCreated(); } private static final Logger log = Logger.getLogger(CustomLock.class); private static ApplicationInstanceListener subListener; /** Randomly chosen, but static, high socket number */ public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331; /** Must end with newline */ public static final String SINGLE_INSTANCE_SHARED_KEY = "$$NewInstance$$\n"; private static ServerSocket socket; /** * Registers this instance of the application. * * @return true if first instance, false if not. */ public static boolean registerInstance() { // returnValueOnError should be true if lenient (allows app to run on network error) or false if strict. boolean returnValueOnError = true; // try to open network socket // if success, listen to socket for new instance message, return true // if unable to open, connect to existing and send new instance message, return false try { socket = new ServerSocket(SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress.getByAddress(new byte[]{127,0,0,1})); socket.setReuseAddress(true);//allows the socket to be bound even though a previous connection is in a timeout state. socket.bind(new InetSocketAddress(SINGLE_INSTANCE_NETWORK_SOCKET)); log.debug("Listening for application instances on socket " + SINGLE_INSTANCE_NETWORK_SOCKET); Thread instanceListenerThread = new Thread(new Runnable() { public void run() { boolean socketClosed = false; while (!socketClosed) { if (socket.isClosed()) { socketClosed = true; } else { try { Socket client = socket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); String message = in.readLine(); if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(message.trim())) { log.debug("Shared key matched - new application instance found"); fireNewInstance(); } in.close(); client.close(); } catch (IOException e) { socketClosed = true; } } } } }); instanceListenerThread.start(); // listen } catch (UnknownHostException e) { log.error(e.getMessage(), e); return returnValueOnError; } catch (IOException e) { log.debug("Port is already taken. Notifying first instance."); try { Socket clientSocket = new Socket(InetAddress.getByAddress(new byte[]{127,0,0,1}), SINGLE_INSTANCE_NETWORK_SOCKET); OutputStream out = clientSocket.getOutputStream(); out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes()); out.close(); clientSocket.close(); log.debug("Successfully notified first instance."); return false; } catch (UnknownHostException e1) { log.error(e.getMessage(), e); return returnValueOnError; } catch (IOException e1) { log.error("Error connecting to local port for single instance notification"); log.error(e1.getMessage(), e1); return returnValueOnError; } } return true; } public static void setApplicationInstanceListener(ApplicationInstanceListener listener) { subListener = listener; } private static void fireNewInstance() { if (subListener != null) { subListener.newInstanceCreated(); } } public static void closeInstance() { if (socket != null) { try { socket.close(); } catch (IOException e) { log.error("Error while closing the socket"); } } } } </code></pre> <p>I tryed the code and it works really well under Linux. if i close the application (even trying to kill it) the socket is immediatly released and i can launch a new application! Unfortunatelly under windows thinks are not so easy. once the resource is allocated is never released. if i close the software i will not be able to launch it again till i close my section.</p> <p>Any idea about how fix nicelly the code to make it works under windows. I tought i could use a shut down hook to catch at least the normal shutting down. Do not really know instead wat to do in case he process terminates in an unexpected way.</p> <p>Here i attach a print screen done over the SW TCPView that shoes how the port is kept open by java: <img src="https://i.stack.imgur.com/8wtx9.png" alt="enter image description here"></p> <p>I tryed implementing a much simpler version. still the same problem. under windows the resources are not released.</p> <p>Here is the second code:</p> <pre><code>import java.net.ServerSocket; import javax.swing.JOptionPane; import javax.swing.JFrame; import java.io.IOException; import java.net.BindException; class MyApplication{ public static ServerSocket serverSocket; public static void main(String as[]) { try { //creating object of server socket and bind to some port number serverSocket = new ServerSocket(15486); ////do not put common port number like 80 etc. ////Because they are already used by system JFrame jf = new JFrame(); jf.setVisible(true); jf.setSize(200, 200); } catch (BindException exc) { JOptionPane.showMessageDialog(null, "Another instance of this application is already running.", "Error", JOptionPane.ERROR_MESSAGE); System.exit(0); } catch (IOException exc) { JOptionPane.showMessageDialog(null, "Another instance of this application is already running.", "Error", JOptionPane.ERROR_MESSAGE); System.exit(0); } } } </code></pre> <p>There is somethink that does not clse properly. It does not work if i put in the shutdown hook the followin code as well:</p> <p>// shut down server </p> <pre><code>try{ serverSocket.close(); }catch (IOException e) { e.printStackTrace(); } </code></pre> <p>Thanks in advance</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload