Можете ли вы объяснить процесс подключения HttpURLConnection?

я использую HTTPURLConnection для подключения к веб-службе. Я знаю, как использовать HTTPURLConnection но я хочу понять, как это работает. В принципе, я хочу знать следующее:

  • на какой момент делает HTTPURLConnection попробуйте установить соединение с заданным URL-адресом?
  • в какой момент я могу знать, что мне удалось успешно установить соединение?
  • устанавливают соединение и отправляют фактический запрос, выполненный за один шаг/вызов метода? Какой метод это?
  • можете ли вы объяснить функцию getOutputStream и getInputStream в непрофессиональном смысле? Я замечаю, что когда сервер, к которому я пытаюсь подключиться, не работает, я получаю Exception at getOutputStream. Значит ли это, что HTTPURLConnection начнет устанавливать соединение только при вызове getOutputStream? Как насчет getInputStream? Поскольку я могу получить ответ только на getInputStream, значит ли это, что я не отправлял никаких запросов в getOutputStream но просто устанавливает соединение? Do HttpURLConnection вернуться на сервер запрос ответа при вызове getInputStream?
  • правильно ли я говорю, что openConnection просто создает новый объект соединения, но пока не устанавливает никакого соединения?
  • как я могу измерить прочитанные накладные расходы и подключить накладные расходы?

4 ответов


String message = URLEncoder.encode("my message", "UTF-8");

try {
    // instantiate the URL object with the target URL of the resource to
    // request
    URL url = new URL("http://www.example.com/comment");

    // instantiate the HttpURLConnection with the URL object - A new
    // connection is opened every time by calling the openConnection
    // method of the protocol handler for this URL.
    // 1. This is the point where the connection is opened.
    HttpURLConnection connection = (HttpURLConnection) url
            .openConnection();
    // set connection output to true
    connection.setDoOutput(true);
    // instead of a GET, we're going to send using method="POST"
    connection.setRequestMethod("POST");

    // instantiate OutputStreamWriter using the output stream, returned
    // from getOutputStream, that writes to this connection.
    // 2. This is the point where you'll know if the connection was
    // successfully established. If an I/O error occurs while creating
    // the output stream, you'll see an IOException.
    OutputStreamWriter writer = new OutputStreamWriter(
            connection.getOutputStream());

    // write data to the connection. This is data that you are sending
    // to the server
    // 3. No. Sending the data is conducted here. We established the
    // connection with getOutputStream
    writer.write("message=" + message);

    // Closes this output stream and releases any system resources
    // associated with this stream. At this point, we've sent all the
    // data. Only the outputStream is closed at this point, not the
    // actual connection
    writer.close();
    // if there is a response code AND that response code is 200 OK, do
    // stuff in the first if block
    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
        // OK

        // otherwise, if any other status code is returned, or no status
        // code is returned, do stuff in the else block
    } else {
        // Server returned HTTP error code.
    }
} catch (MalformedURLException e) {
    // ...
} catch (IOException e) {
    // ...
}

первые 3 ответа на ваши вопросы перечислены как встроенные комментарии, рядом с каждым методом, в Примере HTTP POST выше.

С getOutputStream:

возвращает выходной поток, который записывает в это соединение.

в принципе, я думаю, что у вас есть хорошее понимание того, как это работает, поэтому позвольте мне просто повторить, с точки зрения непрофессионала. getOutputStream в основном открывает подключение поток, с намерением записать данные на сервер. В приведенном выше примере кода "сообщение" может быть комментарием, который мы отправляем на сервер, представляющий комментарий, оставленный на сообщении. Когда вы видите getOutputStream, вы открываете подключение поток для записи, но вы на самом деле не пишете никаких данных, пока не позвоните writer.write("message=" + message);.

С getInputStream():

возвращает входной поток, который читает из этого соединения. Ля SocketTimeoutException может быть вызвано при чтении из возвращенного входного потока, если тайм-аут чтения истекает до того, как данные будут доступны для чтения.

getInputStream совсем наоборот. Как getOutputStream, это подключение поток, но цель состоит в том, чтобы читать данные с сервера, а не писать на него. Если соединение или открытие потока не удается, вы увидите SocketTimeoutException.

как насчет getInputStream? Поскольку я могу получить только ответ в getInputStream, значит ли это, что я еще не отправил запрос в getOutputStream, а просто устанавливает соединение?

имейте в виду, что отправка запроса и передачи данных-это две разные операции. При вызове getOutputStream и getInputStream url.openConnection(), вы отправляете запрос на сервер для установления соединения. Существует рукопожатие, которое происходит, когда сервер отправляет вам подтверждение того, что соединение установленный. Именно в этот момент времени вы готовы отправить или получить данные. Таким образом, вам не нужно вызывать getOutputStream в установить подключение откройте поток, если ваша цель для создания запроса-отправить данные.

в терминах непрофессионала, делая getInputStream запрос-это эквивалент телефонного звонка в дом вашего друга, чтобы сказать: "Эй, ничего, если я приду и одолжу эту пару тисков?"и ваш друг устанавливает рукопожатие со словами: "Конечно! Иди и возьми его". Затем, в этот момент, связь установлена, вы идете к дому своего друга, стучите в дверь, просите тиски и возвращаетесь домой.

используя аналогичный пример для getOutputStream будет включать в себя вызов вашего друга и сказать: "Эй, у меня есть деньги, которые я должен вам, могу ли я отправить его вам"? Твой друг, нуждающийся в деньгах и больной внутри, что ты хранил их так долго, говорит: "Конечно, иди сюда, дешевый ублюдок". И ты идешь к своей ... дом друга и" отправить " ему деньги. Затем он выгоняет тебя, и ты возвращаешься домой.

теперь, продолжая пример непрофессионала, давайте рассмотрим некоторые исключения. Если вы позвонили своему другу и его не было дома, это может быть 500 ошибка. Если вы позвонили и получили сообщение об отключенном номере, потому что ваш друг устал от того, что вы все время занимаете деньги, это страница 404 не найдена. Если ваш телефон мертв, потому что вы не оплатили счет, это может быть исключение IOException. (Примечание: этот раздел может быть не на 100% правильным. Он призван дать вам общее представление о том, что происходит с точки зрения непрофессионала.)

Вопрос № 5:

Да, вы правы, что openConnection просто создает новый объект соединения, но не устанавливает его. Соединение устанавливается при вызове getInputStream или getOutputStream.

openConnection создает новый объект Connection. От URL-адрес.документации, содержащие вредоносные элементы:

новое соединение открывается каждый раз путем вызова метода openConnection обработчика протокола для этого URL-адреса.

соединение устанавливается при вызове openConnection,а InputStream, OutputStream или оба вызываются при их создании.

Вопрос № 6:

чтобы измерить накладные расходы, я обычно обертываю очень простое время код вокруг всего блока подключения, например, так:

long start = System.currentTimeMillis();
log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );

// run the above example code here
log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );

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

для получения информации о закрытии соединений, о которых вы не спрашивали, см. в Java, когда соединение URL закрывается?.


Тим Брей представил краткий шаг за шагом, заявив, что openConnection() не устанавливает фактического соединения. Скорее, фактическое HTTP-соединение не устанавливается, пока вы не вызовете такие методы, как getInputStream() или getOutputStream().

http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection


на каком этапе HTTPURLConnection пытается установить соединение с данным URL-адресом?

на порту, названном в URL-адресе, если таковой имеется, в противном случае 80 для HTTP и 443 для HTTPS. Я считаю, что это задокументировано.

в какой момент я могу знать, что мне удалось успешно установить соединение?

при вызове getInputStream() или getOutputStream() или getResponseCode () без получения исключения.

устанавливаете соединение и отправляете фактический запрос, выполненный за один шаг/вызов метода? Что это за метод?

нет и нет.

можете ли вы объяснить функцию getOutputStream и getInputStream в термине непрофессионала?

любой из них сначала подключается при необходимости, затем возвращает требуемый поток.

Я замечаю, что когда сервер, к которому я пытаюсь подключиться, не работает, я получаю исключение на getOutputStream. Означает ли это, что HTTPURLConnection начнет устанавливать соединение только при вызове getOutputStream? Как насчет getInputStream? Поскольку я могу получить ответ только в getInputStream, значит ли это, что я еще не отправил запрос в getOutputStream, а просто установил соединение? HttpURLConnection возвращается на сервер для запроса ответа при вызове getInputStream?

см. выше.

Я правильно сказать, что openConnection просто создает новый объект соединения, но пока не устанавливает никакого соединения?

да.

Как я могу измерить накладные расходы на чтение и подключить накладные расходы?

подключение: взять getInoutStream времени() и getOutputStream (), чтобы вернуть, какой бы вы позвонить. Read: время от начала первого чтения до получения EOS.


на каком этапе HTTPURLConnection пытается установить соединение с данным URL-адресом?

Это стоит уточнить, есть 'UrlConnection' экземпляр и тогда есть базовый подключение сокета Tcp/Ip/SSL, 2 разных понятия. Экземпляр "UrlConnection" или "HttpUrlConnection" является синонимом одного запроса страницы HTTP и создается при вызове url.содержащие вредоносные элементы(). Но если вы делаете несколько url-адрес.openConnection () из одного экземпляра "url", тогда, если Вам повезет, они будут повторно использовать тот же сокет Tcp/Ip и SSL-рукопожатие...что хорошо, если вы делаете много запросов страниц на один и тот же сервер, особенно хорошо, если вы используете SSL, где накладные расходы на создание сокета очень высоки.

посмотреть: реализация HttpURLConnection