2011-10-04 6 views
0

응용 프로그램을 다시 시작하면 BindException이 발생합니다. 원격 제어 메시지를 기다리는 서버의 역할을합니다. ServerSocket은 백그라운드 스레드 (AsyncTask)에서 실행 중입니다. 내 응용 프로그램을 다시 시작한 후에는 항상 위에서 언급 한 예외가 발생합니다. 나는 그것을 듣기 위해 항구에 다시 묶을 때까지 10 분을 기다려야 만한다.응용 프로그램을 다시 시작한 후 "BindException : 주소가 이미 사용 중입니다"

내 포트를 차단하는 다른 응용 프로그램이 없으므로 다른 포트 (모두> 50000)를 사용해 보았습니다. 나는 소켓을 닫는 것에주의해야했고 SO_REUSEADDR 옵션을 사용하려고했다. 또한 나는 모든 socketbind를 기록했기 때문에 런타임에 하나의 연결 만 열려 있다고 확신합니다.

그래서 내가 생각하는 것은 연결이 제대로 닫히지 않는다는 것입니다. 나는 즉시 닫지 않는 소켓 습관에 대해 읽었습니다. 하지만 응용 프로그램을 다시 시작할 때마다 10 분을 기다릴 수 없어이 시간을 줄이거 나 종료 할 방법을 찾지 못했습니다.

의견이 있으십니까?

예외 :

10-04 16:39:22.526: WARN/System.err(4974): java.net.BindException: Address already in use 
10-04 16:39:22.526: WARN/System.err(4974):  at org.apache.harmony.luni.platform.OSNetworkSystem.bind(Native Method) 
10-04 16:39:22.526: WARN/System.err(4974):  at dalvik.system.BlockGuard$WrappedNetworkSystem.bind(BlockGuard.java:275) 
10-04 16:39:22.526: WARN/System.err(4974):  at org.apache.harmony.luni.net.PlainSocketImpl.bind(PlainSocketImpl.java:165) 
10-04 16:39:22.526: WARN/System.err(4974):  at java.net.ServerSocket.<init>(ServerSocket.java:123) 
10-04 16:39:22.526: WARN/System.err(4974):  at java.net.ServerSocket.<init>(ServerSocket.java:74) 
10-04 16:39:22.526: WARN/System.err(4974):  at com.*******.remote.RemoteHandlerListener$1.doInBackground(RemoteHandlerListener.java:114) 

코드 :

ServerSocket server; 
try { 
    server = new ServerSocket(); 
    server.setReuseAddress(true); 
    server.bind(new InetSocketAddress(serverport)); 
} catch (IOException e) { 
    e.printStackTrace(); 
    return null; 
} 

while (true) { 
    BufferedReader inStream = null; 
    Socket client = null; 
    try { 
     client = server.accept(); 
     inStream = new BufferedReader(new InputStreamReader(client.getInputStream())); 
     // read from stream 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (inStream != null) { 
      try { 
       inStream.close(); 
      } catch (IOException e) { } 
     } 
     if (client != null) { 
      try { 
       client.close(); 
      } catch (IOException e) { } 
     } 
    } 
} 
try { 
    server.close(); 
} catch (IOException e) { } 

예외는 server.bind 문에 발생합니다.

편집 : 문제의 원인 : accept-call이 차단되어 스레드가 종료되지 않습니다. 프로그램이 완전히 종료되지 않고 소켓이 언 바운드되지 않았습니다.

해결 방법 : 소켓에 SO_TIMEOUT을 설정하고 while() 루프에서 isCancelled를 확인하십시오. 이렇게하면 cancel()을 호출하면 스레드가 완료됩니다.

+0

"restart"및 "background thread"를 정의 할 수 있습니까? 작업 관리자에서 응용 프로그램을 종료하고 다시 시작하거나 .apk를 다시 설치 하시겠습니까? 백그라운드 스레드를 말할 때 AsyncTask 또는 전통적인 Java 스레드를 사용하고 있으며 데몬으로 표시되어 있습니까? 이는 모두 응용 프로그램 수명주기와 VM이 동시성 단위와 함께 작동하는 방식과 관련이 있습니다. –

+0

다시 시작한다는 것은 시작 작업에서 뒤로 버튼을 누른 다음 아이콘을 클릭하여 다시 시작한다는 것을 의미하므로 onDestroy 메서드를 호출하여 스레드를 중지합니다. taskmanager 또는 재설치가 필요하지 않습니다. taskmanager를 통해 응용 프로그램을 종료하면 문제가 해결되지만 실제 해결책은 아닙니다. –

+0

배경 스레드로 AsyncTask를 사용합니다. –

답변

0

모든 catch 된 예외의 스택 추적을 인쇄하십시오. 아마도 도움이 될 것입니다. 어쩌면 게시 한 코드에 잘못된 것이있을 수 있습니다. Exception을 처리하지 않고 try-catch 블록을 작성 중입니다. 어떤 것이 있는지조차 알지 못합니다.


업데이트 : 다음 단계는 응용 프로그램이 실제로 중지되었는지 확인하는 것입니다. 코드 첫눈에 결코 결코 클라이언트를 받아들이 기의 당신의 무한한 반복을 종료하십시오. 문제를 해결하고 serversocket을 닫은 후에 print 문을 추가하십시오.

try { 
    server.close(); 
    System.out.println("Server successfully stopped."); 
} catch (IOException e) { } 

응용 프로그램의 출력에서 ​​찾으십시오.

그리고 당신은 실수가 되길 원한다면, 당신은 사용하여 셧다운 응용 프로그램 (과 ServerSocket의)을 적용 할 수는 :

System.exit(0); 
+0

누락 된 printStackTrace()를 추가했습니다. BindException 이외에는 예외가 발생하지 않습니다. –

+0

그게 문제였습니다. 나는 스레드를 인터럽트하지 않았지만 스레드가 (isCancelled를 통해) 멈추고 스레드가 스스로를 죽여야하는지 확인했다. 들어오는 연결이 없으면 어떻게됩니까? 예, accept() 호출이 차단되어 스레드가 종료되지 않습니다. 이 방법은 실이 멈추지 않았습니다. 어리석은 실수;) –

0

나는 동의 - 일반적으로이 다시 시작 제대로 서버 프로세스를 종료하지 못했음을 나타냅니다. 어쨌든 여전히 실행 중이므로 포트가 계속 차단됩니다.

10 분 동안 기다리는 것이 다소 길다. 이전에 실행중인 java 프로세스가 종료 된 경우 (가능한 경우) 확인하십시오.

+0

그건 유용한 힌트 였어. 응용 프로그램을 수동으로 종료하여 응용 프로그램이 실제로 중지되었는지 확인하십시오. 하지만 어떻게하면 항상 내 응용 프로그램이 종료되었는지 확인하거나 다시 시작할 때 어떻게 종료 할 수 있습니까? –

+0

응용 프로그램을 시작할 때 생성 된 운영 체제 프로세스를 확인한 다음 계속보고 있어야하는 응용 프로그램 프로세스가 있는지 확인합니다. 실행 프로그램의 패키징에 따라 시작된 실행 파일 또는 Java의 이름이됩니다. 작업 관리자/프로세스 목록에서 해당 프로세스를 종료하면 소켓이 닫히지 만 디스크에 일관성없는 상태가 될 수있는 프로세스 인 경우 몇 가지주의를 기울여야합니다. 덜 견고한 응용 프로그램 중 일부는 위험 섹션에서 강제 종료 될 때 다시 시작되지 않습니다. –

0

아직 안드로이드 개발자의 자료를 Activity Lifecycles에서 연구해야합니다.이 기사의 안드로이드 운영 체제는 언제든지 일어날 수있는 경우를 제외하고는 응용 프로그램이 언제 죽을 지에 대해 절대 보장하지 않는다는 것입니다. 그래서 onPause, onResume, onRestart 등을 제공하는 것입니다. 앱이 항상 완전히 죽을 것이라고 절대 보장 할 수는 없지만 자신 만의 정리를 수행 할 수 있습니다. 스레드를 종료하고 onPause 내부에서 소켓 (또는 다른 관리)을 닫는 것이 좋습니다.

또한 Java 소켓 (Android이든 아니든간에)을 사용하는 경우 프로그램 종료가 소켓을 닫는 동작이되도록하는 것은 결코 바람직하지 않습니다. 당신은 일종의 정화 지역에서 거의 항상 자신을 닫아야합니다. 특히 스레드를 다룰 때.

업데이트 : 다시 타격을하고 다시 시작한다고하셨습니다. 이것은 onDestroy를 호출하지 않습니다. onDestroy는 OS가 메모리를 필요로하고 앱을 완전히 죽이는 경우에만 호출됩니다 (작업 관리자에서 종료하는 것과 같습니다)

+0

당신이 옳습니다. onStop()은 내가 생각하는 길이었을 것입니다. –

관련 문제