2013-11-19 6 views
7

У меня есть служба, которая запускает Thread для выполнения некоторых операций с сокетом. Код выглядит следующим образом:java.net.BindException: bind failed: EADDRINUSE (адрес уже используется)

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

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

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

Кроме того, я добавил ServerSocket закрытие в onDestroy методы обслуживания, но это не помогло.

setReuseAddress Выполняется перед bind, так почему он не работает?

+2

Я предлагаю вам войти, когда 'ServerSocket' фактически закрывается. Либо вы повторно используете чужой порт, либо служба не вышла полностью при перезапуске. – EJP

ответ

-1

Насколько я могу догадаться, он застрял на serverSocket.accept(), ожидая соединения, чтобы войти. Следовательно, Runnable никогда не заканчивается даже после закрытия приложения. Вызов приложения снова дает вам эту ошибку (поскольку порт по-прежнему заблокирован Runnable, который был создан до этого). Есть несколько способов обработки:

  • Вы можете позвонить и остановить ваш Runnable так:

    ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor(); 
    Runnable longRunningTask = new Runnable(); 
    Future longRunningTaskFuture = threadPoolExecutor.submit(longRunningTask); 
    longRunningTaskFuture.cancel(true); //this might not trigger right away 
    
  • Вы можете остановить serverSocket.accept() по телефону serversocket.close() (который бросит SocketException, который должен обрабатывается)

  • Я решил (может быть, не так, как правильно это сделать), отправив данные (строку) на мой сервер. Сокет из метода onClose() в моей деятельности:

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

При желании вы можете поймать это на сервере, как это:

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 
} 
+0

В OP нет «Исполнителя». Почему вы думаете, что сверстник должен сериализовать строку «TIMEOUT» - еще одна загадка. -1 – EJP

Смежные вопросы