Android - сокет закрывается недостаточно быстро
У меня есть клиентское приложение и серверное приложение. Клиентское приложение отправляет пакеты на серверное приложение через java.net.Socket (Protocol = TCP). На Socket.Close() мое серверное приложение мгновенно показывает мне, что соединение было закрыто - и вот как оно должно работать должным образом. Примечание: вся логика потокового tcp находится во вторичной активности, поэтому я использую функцию onBackPressed() для завершения всей потоковой передачи tcp и переключения на основную активность.
Рабочий сценарий:
@Override
public void onBackPressed(){
m_socket.Close();
finish();
}
Как объяснено, сокет закрывается, и сервер немедленно уведомляет, что соединение было закрыто.
Неработающий сценарий, так как Socket.close() кажется слишком медленным:
@Override
public void onBackPressed(){
m_socket.Close();
m_wifiManager.disconnect();
finish();
}
Этот сценарий работает правильно только в 20% случаев. В остальные 80% мое серверное приложение уведомляет, что соединение было закрыто с большой задержкой. По моему мнению, это из-за времени, необходимого для закрытия tcp-сокета - поэтому процесс прерывается из-за разрыва соединения Wi-Fi и не может быть правильного закрытия сокета (#). В качестве доказательства моего мнения: этот сценарий работает в 100% случаев, если я отлаживаю его шаг за шагом. Сервер уведомляет немедленно.
Что я уже пробовал и что тоже не работает должным образом:
m_wifiManager.disconnect()
вonPause()
m_wifiManager.disconnect()
вonDestroy()
Итак, мои вопросы:
Правильно ли мое мнение (#)? Не хватает ли времени для закрытия сокета?
Как это исправить? Так что закрытие tcp-сокета завершается правильно, как в первом сценарии, а после этого отключается wifi?
1 ответ
Проблема, вероятно, связана с опцией сокета SO_LINGER:
Укажите время ожидания при задержке. Эта опция отключает / включает немедленный возврат из close() сокета TCP. Включение этой опции с ненулевым целочисленным таймаутом означает, что close() будет блокировать в ожидании передачи и подтверждения всех данных, записанных в одноранговый узел, после чего сокет будет корректно закрыт. По истечении времени ожидания задержка сокет принудительно закрывается с помощью протокола TCP RST. Включение опции с таймаутом, равным нулю, немедленно приводит к принудительному закрытию. Если указанное значение времени ожидания превышает 65 535, оно будет уменьшено до 65 535.
По умолчанию он отключен, ваш close
звонок немедленно возвращается, и вы отключаете Wi-Fi, прежде чем розетка была фактически закрыта. Вам нужно вызвать setSoLinger, чтобы исправить это:
m_socket.setSoLinger(true, 1);