2012-03-15 1 views
0

IPStringI는 다음과 같이 작동하는 매우 간단한 Activity를가집니다. onCreate에 을 호출하고 독점 포트를 통해 원격 서버에 AsyncTask TCP 소켓 연결을 호출 한 다음 빠른 ASCII 명령을 보냅니다. 서버에서 처리하고 onPostExecute()를 통해 응답을 처리합니다. 훌륭한 작품, 빠르고 기능적입니다.doInBackground가 TCP 소켓에서 멈추었을 때 asynctask를 죽이는 경우

원격 서버가 다운되었거나 잘못된 IP 주소로 잘못 입력 한 경우 - AsyncTask가 "로그인"대화 상자가 멈추고 화면이 회전하는 동안 소켓이 타임 아웃했다.

저는 지난 2 일 동안 cancel()을 호출하는 방법을 찾으려고 노력했지만 실패했습니다. 어떤 제안?

public class Scratchpad extends AsyncTask<Object, String, String>{ 
private String returningResponse; 
private volatile Socket socket; 

@Override 
protected void onPreExecute(){ 
    //throw the "Logging In" dialog up 
    initializeDialog();  
    super.onPreExecute(); 
} 
@Override 
protected void onProgressUpdate(String... values) { 
    super.onProgressUpdate(values); 
} 
@Override 
protected void onPostExecute(String result) { 
    //send the ASCII result off to the function that parses through it 
    loginTriggerResult(result); 
    super.onPostExecute(result); 
} 
@Override 
protected String doInBackground(Object... params) { 
     /* 
     * bunch of stuff goes here to strip out the proper 
     * values from the Object for IP address, Port number etc. 
     * params[0], params[1] etc. 
     * 
     */ 
    InetAddress serverIP = null; 
    String IPString = (String) params[1]; 
    int portnumber = (Integer) params[2]; 

    //convert the String "IPString" into an InetAddress 
    try { 
     serverIP = InetAddress.getByName(IPString); 
    } catch (UnknownHostException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 
    //and then, bingo bango bongo, make the connection with the 'try': 
    try{ 
     socket = new Socket(serverIP.getHostAddress(), portnumber); 
     //I tried this too, forcing the timeout... It crashes immediately. 
     //SocketAddress socketAddress = new InetSocketAddress(serverIP.getHostAddress(), portnumber); 
     //socket.connect(socketAddress, 3000); 
     Log.d("networking","Connection Completed"); 

     //bunch of stuff goes here that happens AFTER the solid connection, 
     //which we never get to if the Socket fails on a "waiting to connect" thing. 

     //reader.close(); 
     //outputStream.close(); 

    }catch (SocketException e){ 
     e.printStackTrace(); 
     Log.w("socket","socket closed with SocketException"); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     Log.w("socket","socket closed with IOException"); 
    }  
    return returningResponse; //postExecute will handle this. 
} 

}

나는 3 사분 때까지 로그 메시지 중 하나가받지 못했습니다 그 소켓 시간 초과 전달합니다 다음은 현재 코드입니다. TimerTask 또는 AsyncTask 외부에서 뭔가를 실행하여 AsyncTask 내부에서 실행중인 'try'를 연결 (또는 연결 안 함)하고 어떻게 든 "취소()"하는 데 걸리는 시간을 추적해야한다고 생각하고 있습니다. ,하지만 나는 수많은 스타일에 실패했습니다.

이 항목은 일반적으로 사용되는 것으로되어 있으며, 쉬운 해결책이 있습니까?

UPDATE : 나는 아래로 향하고 있었다 "자체 모니터링", 그것은 단단한 연결을받지 않고 시간이 초과하는 경우는 if/위해 AsyncTask를 내에서 소켓 연결을 사용하려고 시도 된 경로 - 취소 트리거() AsyncTask. 소켓 시간 초과의 IOException catch 내에서 this.cancel()을 사용하여 AsyncTask 자체에서이 작업을 수행하려고했습니다.

지금까지의 해결책은 AsyncTask와 동시에 시작되는 AsyncTask 외부의 타이머를 구현하는 것입니다. 그러나 많은 초가 지나면 취소 할 수 있습니다. 이 솔루션은 정상적으로 연결 시도를 종료하고, AsyncTask의 onCancelled() 스 D 자 안에 대화 상자 트리거 또는 토스트를 넣을 수 있습니다. 더 이상 충돌이 발생하지 않지만, 작업이 취소 되더라도 소켓은 계속 백그라운드에서 연결을 시도하고 있습니다.

+1

그래서'socket.connect (socketAddress, 3000);'를 시도했지만 즉시 충돌한다고합니다. '즉시'를 어떻게 정의합니까? 3 초 미만? 또한 충돌이 발생하면 logcat에 던져진 예외를 보여주는 무언가가있을 것입니다 - 무엇입니까? 이 호출을 사용하여'connect'를 타임 아웃으로 사용하는 것은 당신이 원하는 것을 정확하게하는 올바른 방법입니다. – Squonk

+0

"즉시"충돌이 발생합니다. 활동이 시작되자 마자 3 초가 지나면 안됩니다. – Octoth0rpe

+0

dalvikvm : threadid = 11 : catch되지 않은 예외로 종료하는 스레드 ... 심각한 예외 : AsyncTask # 1 – Octoth0rpe

답변

0

확실히 connect()를 호출했을 때 제한 시간을 설정하는 것이 가장 간단한 솔루션 인 것 같습니다. 연결 시간 초과가 실패 할 때 생성 된 스택 추적을 게시 할 수 있습니까?

+0

NULL 이니, 실행하기 전에 소켓에 ​​대한 다른 호출을 초기화하는 것을 완전히 잊었 기 때문에 NULL입니다. '소켓 소켓 = 새로운 소켓(); socket.connect (socketAddress, 3000); ' – Octoth0rpe

0

정확히 무엇을하려고합니까? 잘못된 IP 주소를 입력했거나 서버가 다운되었을 때를 감지합니까? 특정 시간 동안 로그인 만 표시 하시겠습니까? 비동기 작업을 취소하는 방법을 묻는 것 같지만 해결할 문제의 근원은 아닌 것 같습니다.

MisterSquonnk이 정확하다고 생각합니다. 전화 연결시 제한 시간을 설정할 수 있습니다. 시간 제한이 작동하지 않으면 코드에서 다른 부분이 손상되었을 수 있습니다. 또는 소켓을 사용하지 않고 자신 만의 타임 아웃을 할 수있게하려면 다음을 참조하십시오.

소켓 연결에 걸린 시간보다 짧은 시간 안에 연결에 실패했다고 가정하려는 경우 타임 아웃 시간을 원하는 시간에 비동기 작업을 시작할 때 새로운 CountDownTimer http://developer.android.com/reference/android/os/CountDownTimer.html을 활동의 같은 위치에 동시에 시작하십시오.

타이머가 만료 된 후 (타이머에서 onFinish가 호출 된 후) 비동기 작업에서 cancel을 호출하거나 onPostExecute가 실행되지 않도록하고 UI에서 로그인 시도가 실패 할 때 수행하려는 작업을 수행하십시오. 마찬가지로 타이머가 만료되기 전에 로그인 시도가 성공하면 타이머를 취소하거나 onFinish가 호출되지 않도록합니다.

+0

아마도 내 문제는 AsyncTask 자체의 실행으로 발생합니다. 나는 (onCreate 내에서) 전화하고있다 : 'new Scratchpad(). (CommandObjects);' 어쩌면 내가 다른 곳에서 참조 할 수있는 뭔가를 만들어야 할까? 'Scratchpad theAsyncTask_thing; '여기에 – Octoth0rpe

+0

처럼이 코멘트 기능의 "shift-enter"실패에 대해 비명을 지르는 부분이 없습니다. – Octoth0rpe

+0

비동기 작업은 다른 Java 개체와 동일하므로 대부분의 예제에서는 표시하지 않지만 항상 참조 할 수 있습니다. AsyncTask myTask = new AsyncTask(); myTask.execute(); –

관련 문제