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
、友達に電話して、「おい、私はあなたに借りているお金があります。送金できますか?」あなたの友人は、お金と病気を必要としていて、あなたがそれを長い間それを保ったので、「確かに、あなたに安い野郎をやって来なさい」と言います。それで、あなたはあなたの友人の家に歩いて、彼にお金を「ポスト」します。それから彼はあなたを追い出し、あなたはあなたの家に戻ります。
さて、素人の例を続けて、いくつかの例外を見てみましょう。あなたがあなたの友人に電話をかけたが、彼が家にいなかった場合、それは500エラーの可能性がある。友達がいつもお金を借りるのに飽き飽きしていて、電話が切れて番号メッセージが届いた場合、それは404ページが見つかりません。請求書を支払わなかったためにスマートフォンが死んでいる場合は、IOExceptionである可能性があります。(注:このセクションは100%正確ではない場合があります。これは、素人の言葉で何が起こっているかについての一般的な考えを提供することを目的としています。)
質問5:
はい、あなたは正しいです。openConnectionは単に新しい接続オブジェクトを作成するだけで、確立しません。getInputStreamまたはgetOutputStreamを呼び出すと、接続が確立されます。
openConnection
新しい接続オブジェクトを作成します。URL.openConnectionののjavadoc:
この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接続はいつクローズするかを参照してください。。