java.net.BindException: bind failed: EADDRINUSE (Address already in use)

你说的曾经没有我的故事 提交于 2020-01-03 08:28:20

问题


I have a service, which starts Thread to perform some operations on socket. The code looks like:

 public class ServerRunnable implements Runnable {
    @Override
    public void run() {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(ProtocolConstants.USB_SERVER_PORT));
        while (true) {
            Socket client = serverSocket.accept();
            // some code
        } catch (Exception e) {
            Log.e("Exception while listening on socket.", e);
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    Log.e(e);
                }
            }
        }

When I start service first time, everything is ok, but then I have to stop it using stopService method. When I start it one more time it returns following exception:

java.net.BindException: bind failed: EADDRINUSE (Address already in use)

In addition I added ServerSocket closing in onDestroy method of service but it did not help.

The setReuseAddress is performed before bind, so why it is not working?


回答1:


As far as I can guess it gets stuck on serverSocket.accept(), waiting for a connection to come in. Hence the Runnable does never finish even after closing the app. Calling the app again gives you this error (because the port is still blocked by the Runnable that was created before that). There are multiple ways of handling this:

  • You can call and stop your Runnable like this:

    ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor();
    Runnable longRunningTask = new Runnable();
    Future longRunningTaskFuture = threadPoolExecutor.submit(longRunningTask);
    longRunningTaskFuture.cancel(true); //this might not trigger right away
    
  • You can stop the serverSocket.accept() by calling serversocket.close() (which will throw a SocketException that needs to be handled)

  • I solved this (might not be the correct way to handle this) by sending data (a string) to my serverSocket from the onClose() method in my Activity:

    Socket socket = new Socket();
    socket.setReuseAddress(true);
    socket.connect((new InetSocketAddress(YOURSETTINGS, HERE);
    OutputStream os = socket.getOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(os);
    oos.writeObject(new String("TIMEOUT"));
    oos.close();
    os.close();
    socket.close();
    

You can optionally catch this in your server like this:

ObjectInputStream objectInputStream = new objectInputStream(serverSocket.getInputStream());
Object object = objectInputStream.readObject();
if (object.getClass().equals(String.class) && ((String) object).equals("TIMEOUT"))
{
//Here you can do something with the Runnable before it is gone
}


来源:https://stackoverflow.com/questions/20068710/java-net-bindexception-bind-failed-eaddrinuse-address-already-in-use

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!