2011-11-04 69 views
3

我已經實現了我自己的Android服務如下的Java的ServerSocket和Android LocalServerSocket

public class MyService extends Service { 
    private static final String TAG = "MyService"; 

    private Server mServer; 
    private LocalServerSocket server; 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     Log.d(TAG, "onCreate"); 
     mServer = new Server(); 
     mServer.start(); 
    } 

    @Override 
    public void onDestroy() { 
     Log.d(TAG, "onDestroy"); 
     if(server != null){ 
      try { 
       server.close(); 
      } catch (IOException e) { 
       Log.d(TAG, "exception in server close"); 
       e.printStackTrace(); 
      } 
     } 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     Log.d(TAG, "onStart"); 
     return START_STICKY; 
    } 

    class Server extends Thread { 
    @Override 
     public void run() { 
      try { 
       server = new LocalServerSocket("my.socket"); 
       while (true) { 
        LocalSocket receiver; 
        try{ 
         receiver = server.accept(); 
        }catch(SocketException e){ 
         Log.d(TAG, "SocketException"); 
         break; 
        } 
        catch(IOException e){ 
         Log.d(TAG, "IOException"); 
         break; 
        } 
        if (receiver != null) { 
         Log.d(TAG, "Got Data in receiver"); 
        } 
        receiver.close(); 
       } 
      } catch (IOException e) { 
       Log.d(TAG, "one more"); 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

我現在面臨的問題是,如果我的LocalServerSocket阻止在接受(),然後調用server.close( )在OnDestroy()不會拋出一個SocketException。因此,下次啓動服務時,我會收到「地址已在使用異常」。如果不是LocalServerSocket,我使用java.net.Socket,那麼我會得到所需的行爲。我想知道爲什麼LocalServerSocket與Java Sockets的行爲不同。在我的情況下,我如何擺脫while循環。

回答

0

從您發佈的代碼看,您的LocalServerSocket server將永遠保持nullonDestroy()將不會關閉它。另外,關閉套接字通常不應該拋出IOException - 但是如果套接字同時關閉,accept()將會這樣做。

+0

那麼你的意思是我應該創建另一個線程來關閉套接字?我試過了,但問題依然存在。只要我等待accept(),我無法再使用該地址!有什麼解決我的代碼? – Manas

2

我有同樣的問題,並「解決」這種方式。線程run()方法正在檢查「!isInterrupted()」。我添加到我的Listener-Thread的方法「stopSocketServer()」標記爲interrupt()的線程,然後向自己發出連接請求以觸發accept()方法。

/** 
* Executed if thread is started. 
*/ 
public void run() { 

    try { 
     // leave while loop if thread is marked for interrupt. 
     while (!isInterrupted()) { 
      LocalSocket clientSocket = serverSocket.accept(); 

      if (!isInterrupted()) { 
       threadPool.execute(new ClientProcessor(clientSocket)); 
      } 
     } 

    } catch (IOException e) { 
     if (!isInterrupted()) { 
      Log.e(TAG, "socket listener terminated", e); 
     } 
    } finally { 
     try { 
      if (serverSocket != null) { 
       serverSocket.close(); 
      } 
      if (threadPool != null) { 
       threadPool.shutdownNow(); 
      } 
      Log.i(TAG, "socket listener stopped"); 
     } catch (IOException e) { 
     } 
    } 
} 

public void stopSocketServer() { 
    if (serverSocket != null) { 
     try { 
      // mark thread as interrupted 
      interrupt(); 

      // now send connect request to myself to trigger leaving accept() 
      LocalSocket ls = new LocalSocket(); 
      ls.connect(serverSocket.getLocalSocketAddress()); 
      ls.close(); 
     } catch (IOException e) { 
      Log.e(TAG, "stopSocketServer failed", e); 
     } 
    } 
}