2012-01-26 2 views
1

파일 전송이 있고 장치가 인터넷 연결을 끊을 때
DataOutputStream.write은 거의 확실하게 블로킹됩니다.howto는 쓰기 블록을 해제하기 위해 socket.close를 강제 실행합니다.

기본 소켓 레이어가 할 수있는 한 빨리 작업을 수행하기 때문에 이것이 정상적이라는 것을 알고 있습니다.

은 내가 socket.close() 또는 DataOutputStream.close()
블록 정상적인 코드의 흐름이 빠른
을 발생하게 중지 DataOutputStream.write을 강제로 이런 일 때

registerReceiver(mConnRec,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 

및 캐치를 사용 할 생각했다.

이 방법이 효과가 있습니까? 아니면 차단 기능을 제어하려면 어떻게해야합니까?

은 내가 가진 또 다른 IDE는 내가 어쩌면 socket.close을 강제 할 수 false를 반환하면이

public boolean haveNetworkConn(Context ctx) 
{ 
    boolean HaveConnectedWifi = false; 
    boolean HaveConnectedMobile = false; 

    ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo[] netInfo = cm.getAllNetworkInfo(); 

    for (NetworkInfo ni : netInfo) 
    { 
     if (ni.getTypeName().equalsIgnoreCase("WIFI")) 
      if (ni.isConnected()) 
       HaveConnectedWifi = true; 
     if (ni.getTypeName().equalsIgnoreCase("MOBILE")) 
      if (ni.isConnected()) 
       HaveConnectedMobile = true; 
    } 
    return HaveConnectedWifi || HaveConnectedMobile; 
} 

같은 존재 매 5 초마다
시험 인터넷입니다 작업 스레드를 시작했다.

정말이 아이디어

UPDATE registerReceiver 브로드 캐스트 리시버를 사용하여 몇 가지 테스트를 실행에 대한 몇 가지 의견이 하시겠습니까.
데이터를 OutputStream 및 소켓 자체에서 닫을 때 아무런 변화가 없습니다. 계속해서 차단을 계속합니다 (out.write(buffer, 0, val);). 이것은 예기치 않은 것이었다.
Eclipse를 사용하고 브레이크 포인트를 배치하고 스테핑 ..

private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 

@Override 
public void onReceive(Context context, Intent intent) { 

    String action = intent.getAction(); 

    if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){ 
     return; 
    } 

    boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 
    NetworkInfo aNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);      

    if (!noConnectivity) 
    { 
     if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) 
     { 
      //Handle connected case 
     } 
    } 
    else 
    { 
     if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) 
     { 
      //Handle disconnected case 
      if(socket != null) 
       try { 
        out.close(); 
        in.close(); 
        socket.close(); 

       } catch (IOException e) { 

       } 
     } 
    } 

} 
}; 

답변

2

예, 소켓을 닫는 것은 현재 소켓에서 차단 호출 모든 방법을 차단하는 방법입니다. the documentation for close()에서 인용하는 것은 :

현재이 소켓에 대한 I/O 조작으로 차단 된 모든 스레드는 SocketException이 발생합니다.

"Java 동시성의 실제"에서 7.1.6 절을 참조하십시오.

CONNECTIVITY_ACTION에 대한 수신기를 등록하는 것은 CPU주기를 절약하고 응용 프로그램의 연결 변경에 대한 반응을 잠재적으로 개선 할 수 있으므로 매 5 초마다 폴링하는 것보다 나은 솔루션입니다.

+0

이것에 대한 테스트 코드를 실행합니다. – Erik

+0

내 질문이 업데이트되었습니다. 테스트를 실행하고 블로킹을 중단하지 않습니다. DataOutputStream.close()가 작동하지 않습니까? 소켓은 IntentService 클래스의 필드이고 소켓은 onHandleIntent()에서 작업 스레드로 전달됩니다. – Erik

+0

이제는 socket.shutdownOutput();을 사용하여 작동합니다. – Erik

관련 문제