как заставить socket.close освободить блок записи - PullRequest
1 голос
/ 27 января 2012

Когда у меня есть передача файла, и устройство теряет подключение к Интернету
, DataOutputStream.write иногда блокируется почти бесконечно.

я знаю, что это нормально, так как нижележащие слои сокетов выполняют свою работу так быстро, как только могут.

Я думал использовать

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

и поймать, когда это произойдет, и сделать socket.close() или DataOutputStream.close()
, чтобы заставить DataOutputStream.write остановить блок и нормальнопоток кода будет происходить на
быстрее.

Будет ли это работать или что я могу сделать, чтобы контролировать блокировку?

Еще одна идея, которую я имел, состояла в том, чтобы запускать поток, работа которого выполняется каждые 5 секунд.
тестирование интернета существует следующим образом

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;
} 

Если это вернет false, я мог бы вызвать socket.close возможно.

Очень бы хотелось получить отзыв об этой идее

ОБНОВЛЕНИЕ Выполнение некоторых тестов с использованием registerReceiver BroadcastReceiver.
Ничего не происходит, когда я закрываю данные и 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) {

                }
        }
     }

}
};

1 Ответ

2 голосов
/ 27 января 2012

Да, закрытие сокета - это способ разблокировать все вызовы методов, которые в данный момент заблокированы в сокете.Цитируя документацию для close():

Любой поток, в настоящее время заблокированный в операции ввода-вывода на этом сокете, вызовет исключение SocketException.

См. Также раздел 7.1.6 в разделе «Практический параллелизм Java».

Регистрация получателя для CONNECTIVITY_ACTION - лучшее решение, чем опрос каждые 5 секунд, поскольку он экономит циклы ЦП и потенциально позволяет увеличить задержку в вашемреакция приложения на изменение подключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...