web-dev-qa-db-ja.com

HttpURLConnection接続プロセスを説明できますか?

HTTPURLConnectionを使用してWebサービスに接続しています。 HTTPURLConnectionの使用方法は知っていますが、その仕組みを理解したいと思います。基本的に、私は次のことを知りたいです:

  • HTTPURLConnectionはどの時点で、指定されたURLへの接続を確立しようとしますか?
  • 接続を正常に確立できたことをどの時点で知ることができますか?
  • 接続を確立して実際の要求を送信するのは、1つのステップ/メソッド呼び出しで行われていますか?どのような方法ですか?
  • getOutputStreamgetInputStreamの機能を素人の言葉で説明できますか?接続しようとしているサーバーがダウンすると、ExceptiongetOutputStreamを取得します。 HTTPURLConnectionを呼び出したときにのみ、getOutputStreamが接続の確立を開始するということですか? getInputStreamはどうですか? getInputStreamでのみ応答を取得できるので、getOutputStreamでまだリクエストを送信せずに、単に接続を確立するだけですか? HttpURLConnectionを呼び出したときに、getInputStreamがサーバーに戻って応答を要求しますか?
  • openConnectionは単に新しい接続オブジェクトを作成するが、まだ接続を確立していないと言ってもいいですか?
  • 読み取りオーバーヘッドと接続オーバーヘッドを測定するにはどうすればよいですか?
131
Arci
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) {
    // ...
}

上記のHTTP POSTの例では、質問に対する最初の3つの回答が、各メソッドの横にインラインコメントとしてリストされています。

getOutputStream から:

この接続に書き込む出力ストリームを返します。

基本的に、あなたはこれがどのように機能するかについて十分に理解していると思うので、私は素人の言葉で繰り返してみましょう。 getOutputStreamは基本的に 接続 サーバーにデータを書き込むことを目的としたストリーム。上記のコード例の「メッセージ」は、投稿に残されたコメントを表すサーバーに送信するコメントです。 getOutputStreamが表示されたら、 接続 書き込み用のストリームですが、writer.write("message=" + message);を呼び出すまで実際にはデータを書き込みません。

getInputStream() から:

この開いている接続から読み取る入力ストリームを返します。データが読み取り可能になる前に読み取りタイムアウトが期限切れになった場合、返された入力ストリームから読み取るときにSocketTimeoutExceptionがスローされます。

getInputStreamはその逆です。 getOutputStreamと同様に、 接続 ストリームですが、意図はサーバーにデータを読み込むことであり、サーバーに書き込むことではありません。接続またはストリームを開くことができない場合、SocketTimeoutExceptionが表示されます。

GetInputStreamはどうですか? getInputStreamでのみ応答を取得できるので、getOutputStreamでまだリクエストを送信せず、単に接続を確立するということですか?

要求の送信とデータの送信は2つの異なる操作であることに注意してください。呼び出すとき getOutputStreamまたはgetInputStream url.openConnection()、接続を確立する要求をサーバーに送信します。サーバーが接続が確立されたことを示す確認応答を送り返す場合に発生するハンドシェイクがあります。その時点で、データを送受信する準備が整います。したがって、getOutputStreamを呼び出して 接続を確立する リクエストを行う目的がデータの送信である場合を除き、ストリームを開きます。

素人の言い方をすれば、getInputStreamリクエストを行うことは、友人の家に電話して、「おい、その副グリップを借りても大丈夫ですか?」あなたの友人は「確かに来て、それを手に入れて」と言って握手を確立します。その後、その時点で接続が確立され、友人の家に歩いて行き、ドアをノックして、副グリップを要求し、家に戻ります。

getOutputStreamに同様の例を使用すると、友人に電話して「ねえ、私はあなたに借りがあるお金があります。あなたに送ってもいいですか」と言いますか?あなたの友人は、お金と病気を必要としているので、長い間それを保管していました、「確かに、あなたに安いろくでなしに来てください」と言います。それで、あなたはあなたの友人の家に歩いて、彼にお金を「POST」します。それから彼はあなたを追い出し、あなたはあなたの家に戻ります。

さて、素人の例を続けて、いくつかの例外を見てみましょう。あなたがあなたの友人に電話し、彼が家にいなかった場合、それは500エラーである可能性があります。友人がいつもお金を借りるのにうんざりしているために電話をかけ、切断された番号のメッセージを受け取った場合、404ページは見つかりません。請求書を支払わなかったために電話が故障した場合、それはIOExceptionである可能性があります。 (注:このセクションは100%正確ではない可能性があります。素人の言葉で何が起きているかについての一般的な考えを提供することを目的としています。)

質問5:

はい、openConnectionは単に新しい接続オブジェクトを作成するだけで、それを確立しないのは正しいです。 getInputStreamまたはgetOutputStreamを呼び出すと、接続が確立されます。

openConnectionは、新しい接続オブジェクトを作成します。 RL.openConnection javadocs から:

このURLのプロトコルハンドラーのopenConnectionメソッドを呼び出すことにより、毎回新しい接続が開かれます。

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

要求時間とオーバーヘッドを測定するためのより高度な方法があると確信していますが、これは一般に私のニーズに十分です。

質問しなかった接続のクローズについては、 In Java In URL connection close close? を参照してください。

179
jmort253

ティム・ブレイは、openConnection()が実際の接続を確立しないと述べ、簡潔なステップバイステップを提示しました。むしろ、実際のHTTP接続は、getInputStream()やgetOutputStream()などのメソッドを呼び出すまで確立されません。

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

14
anonymous

HTTPURLConnectionはどのポイントで、指定されたURLへの接続を確立しようとしますか?

URLで指定されているポートがある場合は、HTTPの場合は80、HTTPSの場合は443。これは文書化されていると思います。

接続を正常に確立できたことをどの時点で知ることができますか?

例外を取得せずにgetInputStream()、getOutputStream()、またはgetResponseCode()を呼び出す場合。

接続を確立して実際の要求を送信するのは、1つのステップ/メソッド呼び出しで行われていますか?どのような方法ですか?

いいえ、なし。

GetOutputStreamとgetInputStreamの機能を素人の言葉で説明できますか?

どちらかが最初に必要に応じて接続し、次に必要なストリームを返します。

接続しようとしているサーバーがダウンすると、getOutputStreamで例外が発生します。 getOutputStreamを呼び出すと、HTTPURLConnectionが接続の確立のみを開始するということですか? getInputStreamはどうですか? getInputStreamでのみ応答を取得できるので、getOutputStreamでまだリクエストを送信せず、単に接続を確立するということですか? getInputStreamを呼び出すと、HttpURLConnectionはサーバーに戻って応答を要求しますか?

上記を参照。

OpenConnectionは単に新しい接続オブジェクトを作成するだけで、まだ接続を確立していないと言ってもいいですか?

はい。

読み取りオーバーヘッドと接続オーバーヘッドを測定するにはどうすればよいですか?

接続:getInoutStream()またはgetOutputStream()が戻るのにかかる時間のいずれか早い方を呼び出します。読み取り:最初の読み取りを開始してからEOSを取得するまでの時間。

1
user207421

HTTPURLConnectionは、指定されたURLへの接続を確立しようとしますか?

明確にする価値があり、 'UrlConnection'インスタンスがあり、その後に基礎となるTcp/Ip/SSLソケット接続があります、2つの異なる概念。 「UrlConnection」または「HttpUrlConnection」インスタンスは、単一のHTTPページリクエストと同義であり、url.openConnection()を呼び出すときに作成されます。ただし、1つの「url」インスタンスから複数のurl.openConnection()を実行し、運が良ければ、同じTcp/IpソケットとSSLハンドシェークを再利用します...同じサーバーに対して多くのページ要求を行う。特に、ソケットを確立するオーバーヘッドが非常に大きいSSLを使用している場合に適しています。

参照: HttpURLConnection implementation

1
Tim Cooper