Can You Explain the Httpurlconnection Connection Process

Can you explain the HttpURLConnection connection process?

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) {
// ...
}

The first 3 answers to your questions are listed as inline comments, beside each method, in the example HTTP POST above.

From getOutputStream:

Returns an output stream that writes to this connection.

Basically, I think you have a good understanding of how this works, so let me just reiterate in layman's terms. getOutputStream basically opens a connection stream, with the intention of writing data to the server. In the above code example "message" could be a comment that we're sending to the server that represents a comment left on a post. When you see getOutputStream, you're opening the connection stream for writing, but you don't actually write any data until you call writer.write("message=" + message);.

From getInputStream():

Returns an input stream that reads from this open connection. A SocketTimeoutException can be thrown when reading from the returned input stream if the read timeout expires before data is available for read.

getInputStream does the opposite. Like getOutputStream, it also opens a connection stream, but the intent is to read data from the server, not write to it. If the connection or stream-opening fails, you'll see a SocketTimeoutException.

How about the getInputStream? Since I'm only able to get the response at getInputStream, then does it mean that I didn't send any request at getOutputStream yet but simply establishes a connection?

Keep in mind that sending a request and sending data are two different operations. When you invoke getOutputStream or getInputStream url.openConnection(), you send a request to the server to establish a connection. There is a handshake that occurs where the server sends back an acknowledgement to you that the connection is established. It is then at that point in time that you're prepared to send or receive data. Thus, you do not need to call getOutputStream to establish a connection open a stream, unless your purpose for making the request is to send data.

In layman's terms, making a getInputStream request is the equivalent of making a phone call to your friend's house to say "Hey, is it okay if I come over and borrow that pair of vice grips?" and your friend establishes the handshake by saying, "Sure! Come and get it". Then, at that point, the connection is made, you walk to your friend's house, knock on the door, request the vice grips, and walk back to your house.

Using a similar example for getOutputStream would involve calling your friend and saying "Hey, I have that money I owe you, can I send it to you"? Your friend, needing money and sick inside that you kept it for so long, says "Sure, come on over you cheap bastard". So you walk to your friend's house and "POST" the money to him. He then kicks you out and you walk back to your house.

Now, continuing with the layman's example, let's look at some Exceptions. If you called your friend and he wasn't home, that could be a 500 error. If you called and got a disconnected number message because your friend is tired of you borrowing money all the time, that's a 404 page not found. If your phone is dead because you didn't pay the bill, that could be an IOException. (NOTE: This section may not be 100% correct. It's intended to give you a general idea of what's happening in layman's terms.)

Question #5:

Yes, you are correct that openConnection simply creates a new connection object but does not establish it. The connection is established when you call either getInputStream or getOutputStream.

openConnection creates a new connection object. From the URL.openConnection javadocs:

A new connection is opened every time by calling the openConnection method of the protocol handler for this URL.

The connection is established when you call openConnection, and the InputStream, OutputStream, or both, are called when you instantiate them.

Question #6:

To measure the overhead, I generally wrap some very simple timing code around the entire connection block, like so:

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

I'm sure there are more advanced methods for measuring the request time and overhead, but this generally is sufficient for my needs.

For information on closing connections, which you didn't ask about, see In Java when does a URL connection close?.

What is a java.net.URLConnection doing?

It is fetching the raw HTML of the web page. Similar if you where to open a page in your browser and right click->View Source.

If you connect to a Youtube page, you will get the raw HTML and within that code, will be a reference (href), most likely a tag that points to the source of the video.

--Edit

A browser then obviously interprets that HTML into what you see on your screen.
A modern browser automatically connects to all references on that HTML page, as if loading multiple pages simultaneously, and putting them together.

It's possible know when the HttpURLConnection was established?

Not sure why you would need that information.

You should not care since once you call connect() you can start retrieving the response e.g.

int responseCode = connection.getResponseCode();//Get HTTP status code

Assuming of course you have send all your request to the output stream.

The HttpURLConnection under the hood knows if it is already connected to the server and the implementation reuses the connection (transparent to you).

Now, having said that to answer your question, I think that the only way to know if the HttpURLConnection's state is connected to the server, is to call openConnection() a second time in the same HttpURLConnection object.

If it is already connected it will throw a relevant exception complaining that it is already connected something like: IllegalStateException("Already connected");.

At that point you know that the HttpURLConnection is connected

HttpURLConnection implementation

Should input/output stream be closed
followed by a url.openConnection();
each time to send the new request
(avoiding disconnect())?

Yes.

If yes, I can not see how the connection is being
reused when I call
url.openConnection() for the second
time, since the connection has been
removed from the cache for the first
request and can not find how it is
returned back.

You are confusing the HttpURLConnection with the underlying Socket and its underlying TCP connection. They aren't the same. The HttpURLConnection instances are GC'd, the underlying Socket is pooled, unless you call disconnect().

HttpURLConnection connect method fails to connect

This is what javadoc say about connect() : "Opens a communications link to the resource referenced by this URL, if such a connection has not already been established."

Correct.

So the request should have been sent.

Non sequitur. Thwre is nothing in your quotation about sending the request.

As you have observed, the request is buffered until you perform some input step.

Java URLConnection - When do I need to use the connect() method?

HttpURLConnection conn = (HttpURLConnection) u.openConnection();

only creates an Object

connect() method is invoked by conn.getInputStream();

HttpURLConnection does not send a request if the response is not read

That's the way HttpURLConnection works. It doesn't send the request until you attempt to read the response. You must at least attempt to read the response, even if you aren't interested in the response (although, to be honest, why aren't you checking the response to see if your POST request worked?)

See this question and answer:

Why does HttpURLConnection not send the HTTP request



Related Topics



Leave a reply



Submit