Реализация HttpURLConnection

Я прочитал, что HttpURLConnection поддерживает постоянные соединения, так что соединение может быть повторно использовано для нескольких запросов. Я попробовал это, и единственный способ отправить второй POST - это вызвать openConnection во второй раз. В противном случае я получил IllegalStateException («Уже подключен»); Я использовал следующее:

try{
URL url = new URL("http://someconection.com");
}
catch(Exception e){}
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//set output, input etc
//send POST
//Receive response
//Read whole response
//close input stream
con.disconnect();//have also tested commenting this out
con = (HttpURLConnection) url.openConnection();
//Send new POST

Второй запрос отправляется по тому же TCP-соединению (проверено с помощью wireshark), но я не могу понять почему (хотя это то, что я хочу), так как я назвал отключение. Я проверил исходный код для HttpURLConnection, и реализация поддерживает постоянный кеш подключений к тем же адресатам. Моя проблема в том, что я не могу видеть, как соединение помещается обратно в кеш после отправки первого запроса. Разъединение закрывает соединение и без разъединения все равно не вижу, как соединение снова помещается в кеш. Я видел, что в кеше есть метод run для прохождения всех незанятых соединений (я не уверен, как он называется), но я не могу найти, как соединение помещается обратно в кеш. Единственное место, которое, по-видимому, происходит, находится в готовом методе httpClient, но это не вызывается для POST с ответом. Может кто-нибудь помочь мне в этом?

РЕДАКТИРОВАТЬ Меня интересует, как правильно обрабатывать объект HttpUrlConnection для повторного использования tcp-соединения. Если поток ввода / вывода закрыт, за ним следует url.openConnection (); каждый раз отправлять новый запрос (избегая disconnect ())? Если да, я не могу видеть, как повторно используется соединение, когда я вызываю url.openConnection () во второй раз, так как соединение было удалено из кэша для первого запроса и не могу найти, как оно возвращается обратно. Возможно ли, что соединение не возвращается обратно в кеш-память (ошибка?), Но ОС еще не освободила соединение tcp, а при новом соединении ОС возвращает буферизованное соединение (еще не освобожденное) или что-то подобное? EDIT2 Единственное, что я нашел, было из JDK_KeepAlive

... когда приложение вызывает close () на InputStream, возвращаемом URLConnection.getInputStream (), Обработчик протокола HTTP JDK попытается очистить соединение и, если успешно, поместите соединение в кэш соединений для повторного использования в будущем HTTP-запросы.

Но я не уверен, какой это обработчик. sun.net.www.protocol.http.Handler не выполняет никакого кэширования, как я видел Спасибо!

17
задан atiruz 30 November 2012 в 19:47
поделиться

3 ответа

Если поток ввода / вывода должен быть закрыт за которым следует url.openConnection (); каждый раз отправлять новый запрос (избегая отключения ())?

Да.

Если да, я не вижу, как идет соединение повторно используется, когда я звоню url.openConnection () для второго время, так как соединение было удален из кеша для первого запрос и не могу найти как это вернулся обратно.

Вы путаете HttpURLConnection с базовым Socket и его базовым TCP-соединением. Они не такие. Экземпляры HttpURLConnection хранятся в GC, базовый Socket объединяется в пул, если вы не вызываете disconnect ().

17
ответ дан 30 November 2019 в 12:06
поделиться

Из javadoc для HttpURLConnection (выделено мной):

Каждый экземпляр HttpURLConnection используется для отправки единственного запроса , но базовое сетевое подключение к HTTP-сервер может быть прозрачным разделяется другими экземплярами. Вызов close () для InputStream или OutputStream HttpURLConnection после запроса может освободить сеть ресурсы, связанные с этим экземпляр, но не влияет ни на один общее постоянное соединение. Звонок метод disable () может закрыть базовый сокет, если постоянный в противном случае соединение неактивно время.

7
ответ дан 30 November 2019 в 12:06
поделиться

Я обнаружил, что соединение действительно кэшируется при закрытии InputStream. После закрытия InputStream основное соединение буферизируется. Однако объект HttpURLConnection становится непригодным для дальнейших запросов, поскольку объект считается все еще "подключенным", т.е. его булево connected установлено в true и не очищается, когда соединение помещается обратно в буфер. Таким образом, каждый раз для нового POST необходимо создавать новый HttpUrlConnection, но базовое TCP-соединение будет использоваться повторно, если оно не прервалось. Так что ответ EJP был правильным описанием. Может быть, поведение, которое я видел (повторное использование TCP-соединения), несмотря на явный вызов disconnect(), было вызвано кэшированием, осуществляемым ОС? Я не знаю. Надеюсь, кто-нибудь знающий сможет объяснить. Спасибо.

4
ответ дан 30 November 2019 в 12:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: