1. ホーム
  2. java

[解決済み] HttpURLConnectionの接続処理について教えてください。

2022-05-15 23:47:41

質問内容

私は HTTPURLConnection を使ってウェブサービスに接続しています。私は HTTPURLConnection の使い方は知っていますが、それがどのように機能するのかを理解したいのです。基本的には、次のことを知りたいです。

  • どの点で HTTPURLConnection は与えられたURLへの接続を確立しようとしますか?
  • どの時点で、接続を正常に確立できたことを知ることができますか?
  • 接続の確立と実際のリクエストの送信は、1つのステップ/メソッド呼び出しで行われるのでしょうか?それはどのようなメソッドですか?
  • の機能を説明できますか? getOutputStreamgetInputStream を平たく言うと?私は、接続しようとしているサーバーがダウンしているときに、私が気づくのは ExceptiongetOutputStream . という意味なのでしょうか? HTTPURLConnection を呼び出したときだけ、接続を確立し始めるということでしょうか。 getOutputStream ? では getInputStream ? でしか応答が得られないので getInputStream には何もリクエストを送らなかったということでしょうか? getOutputStream にはまだ何も送っておらず、単に接続を確立しているだけだということですか? そうすると HttpURLConnection を呼び出したら、サーバに戻ってレスポンスを要求するのでしょうか? getInputStream ?
  • ということでよろしいでしょうか? openConnection は単に新しい接続オブジェクトを作成するだけで、まだ接続を確立していないということでよろしいでしょうか?
  • 読み取りオーバーヘッドと接続オーバーヘッドを測定するにはどうすればよいですか?

どのように解決するのですか?

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 は基本的に 接続 ストリームを開き、サーバにデータを書き込むことを意図しています。上記のコード例では、"message" は、投稿に残されたコメントをサーバーに送信していることになります。このとき getOutputStream を開くと 接続 を呼び出すまで、実際にデータを書き込むことはありません。 writer.write("message=" + message); .

から getInputStream() :

このオープン接続から読み込む入力ストリームを返します。返された入力ストリームから読み込む際に、データが読み込めるようになる前に読み込みタイムアウトが終了した場合、SocketTimeoutExceptionがスローされることがあります。

getInputStream はその逆を行います。例えば getOutputStream と同様に 接続 ストリームを開きますが、その目的はサーバーからデータを読み込むことであり、 書き込むことではありません。接続やストリームのオープンに失敗した場合は SocketTimeoutException .

getInputStreamはどうでしょうか?getInputStreamではレスポンスしか取得できていないので、getOutputStreamではまだ何もリクエストを送信しておらず、単に接続を確立しているだけということになるのでしょうか?

リクエストの送信とデータの送信は異なる操作であることに留意してください。リクエストの送信とデータの送信は異なる操作であることに注意してください。 getOutputStream あるいは getInputStream を呼び出すとき url.openConnection() 接続を確立するためにサーバにリクエストを送ります。サーバーが接続が確立されたことを確認するために、ハンドシェイクが行われます。そして、その時点でデータの送受信の準備が整う。したがって、getOutputStream を呼び出す必要はありません。 <ストライク 接続を確立する ストリームを開くために getOutputStream を呼び出す必要はありません。

平たく言えば getInputStream を作ることは、友達の家に電話をかけて、「ねえ、その万力棒を借りに行ってもいい?と言って握手をします。そして、その時点でつながりができ、あなたは友人の家まで歩いて行き、ドアをノックしてバイスグリップを要求し、自分の家まで歩いて帰ります。

同様の例で getOutputStream を使う場合、あなたの友人に電話して、「ねえ、あなたに借りているお金があるんだけど、送らせてくれないかしら?あなたの友人はお金が必要で、あなたが長い間それを保管していたことに内心うんざりしていましたが、「いいよ、来てみろよ、このケチ野郎」と言いました。そこで、あなたは友人の家まで歩いて行き、お金を彼に渡します。そして、彼はあなたを追い出し、あなたは自分の家に戻ります。

さて、素人の例の続きで、いくつかの例外を見てみましょう。友人に電話したところ留守だった場合、500 エラーが発生する可能性があります。電話をかけたら、切断された番号のメッセージが表示された場合、それは 404 ページが見つからなかったということです。もし、あなたが請求書を払わなかったために電話が使えなくなったら、それはIOExceptionの可能性があります。(注:このセクションは100%正しいとは限りません。平易な言葉で何が起こっているのかの一般的なアイデアを提供することを意図しています)。

質問その5です。

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

openConnection は新しい接続オブジェクトを作成します。から URL.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) );

リクエスト時間やオーバーヘッドを測定するためのもっと高度な方法があると思いますが、私のニーズには一般的にこれで十分です。

質問されていない、接続を閉じることに関する情報については Java では、URL 接続はいつ終了するのですか? .