2011-11-04 3 views
3

다음과 같이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이 accept()를 차단하면 OnDestroy()에서 server.close()를 호출하면 문제가 해결되지 않습니다. SocketException를 Throw합니다. 따라서 다음에 서비스를 시작하면 "이미 사용중인 주소 예외"가 발생합니다. LocalServerSocket 대신 java.net.Socket을 사용하면 필요한 동작을 얻습니다. LocalServerSocket이 Java 소켓과 다르게 작동하는 이유를 알고 싶습니다. 내 경우에는 어떻게 while 회 돌이에서 빠져 나옵니까.

답변

0

게시 한 코드에서 LocalServerSocket server은 영원히 null이며, onDestroy()은 종료되지 않습니다. 또한 소켓을 닫으면 정상적으로 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); 
     } 
    } 
} 
관련 문제