#java #android #network-programming #httpurlconnection #persistent
#java #Android #сетевое программирование #httpurlconnection #постоянные
Вопрос:
У меня возникла проблема при попытке заставить приложение Android (ну, сервис, если это имеет какое-либо значение) использовать постоянные соединения HTTP 1.1.
Следующий цикл (упрощенный тестовый пример) работает через один сеанс TCP на настольном JRE, но на устройстве Android приводит ко всему циклу создания / демонтажа сокета.
while (true) {
URL url;
try {
url = new URL("http://10.0.0.125:8080/SRV?");
URLConnection connection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
int responseCode = httpConnection.getResponseCode();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
}
JDK Oracle описывает нечто, называемое «системные свойства»:
http.keepAlive= по умолчанию: true
http.maxConnections= по умолчанию: 5
Есть ли что-то подобное во время выполнения Android, которое предотвращает поддержание постоянных подключений?
Ответ №1:
JVM Android использует встроенную библиотеку Apache HTTP Components для HTTP-подключений (даже тех, которые выполняются с использованием java.net интерфейс): как таковое поведение немного отличается от Oracle JVM.
Теоретически базовый код Harmony учитывает http.keepAlive
системное свойство, но сохраняет ли копия Google это поведение, я не уверен.
Если вы хотите быть абсолютно уверены в том, что происходит, вы должны использовать код HttpComponents. Это долго и болезненно, но если вы посмотрите на http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html в нем описан подход к управлению соединениями для http-компонентов. Посмотрите раздел 2.11, в котором подробно описывается, как явно управлять управлением соединениями с помощью HTTP-компонентов.
Удачи.
Комментарии:
1. В качестве быстрого теста можно попробовать также URLConnection.setRequestProperty(«Подключение», «keep-alive») , если установка требуемого заголовка помогла.
2. Спасибо за указатель в правильном направлении — документация Google не особенно прямолинейна в отношении того факта, что java.net внутренне использует HttpClient от Apache. Я перепишу свой код, используя интерфейсы Apache (и информацию, представленную в 2.11), и буду держать вас в курсе.
3. @harism — похоже, это ничего не меняет.
4. @Femi — каким бы странным это ни было, использование HttpClient, похоже, учитывает «http.keepAlive» — возможно, уровень перевода что-то неправильно настраивает (и не принимает тот факт, что я изменил системное свойство со значений по умолчанию)
5. Это действительно странно. Я никогда не пытался явно устанавливать биты сохранения, но вы правы: вполне возможно, что один из них проскользнул сквозь трещины.
Ответ №2:
Я наблюдал ту же проблему, когда постоянные соединения HTTP 1.1 не устанавливались. Я написал быстрое тестовое приложение, чтобы получить больше деталей.
Сначала я выполнил TCP-дамп трафика из моего приложения, чтобы посмотреть, что происходит. «Connection:keep-alive» правильно отправляется на мой сервер. Затем мой сервер отвечал «Соединение: поддерживается». Однако после того, как мое приложение закрыло InputStream своего соединения, базовый сокет также был закрыт Android … вместо того, чтобы сохраняться.
Чтобы копнуть глубже, я написал свое приложение для подключения, используя два разных подхода:
HttpURLConnection con = (HttpURLConnection) url.openConnection();
И
Клиент HttpClient = новый DefaultHttpClient();
Оказывается, что HttpClient не сохранял базовые сокеты, но HttpURLConnection сохраняет. Поэтому, если вам нужна наилучшая производительность, используйте HttpURLConnections, пока Android не исправит эту ошибку в DefaultHttpClient.
Похоже на ошибку в реализации Android HTTP 1.1?
Комментарии:
1. Используйте HttpURLConnection для приложений, ориентированных на Gingerbread и выше. developer.android.com/training/basics/network-ops /…