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:
返回写入此连接的输出流。
基本上,我认为你对它是如何工作的有很好的理解,所以让我用外行人的话来重申一下。 基本上打开一个连接流,目的是将数据写入服务器。在上面的代码示例中,“message”可能是我们发送到服务器的注释,该注释表示在帖子上留下的评论。当您看到 时,您正在打开连接流进行写入,但在调用 之前,您实际上并没有写入任何数据。getOutputStream
getOutputStream
writer.write("message=" + message);
从 getInputStream():
返回从此打开的连接读取的输入流。如果读取超时在数据可供读取之前过期,则在从返回的输入流读取时,可以引发 SocketTimeoutException。
getInputStream
做相反的事情。就像 ,它还会打开一个连接流,但目的是从服务器读取数据,而不是写入它。如果连接或流打开失败,您将看到 .getOutputStream
SocketTimeoutException
getInputStream 怎么样?由于我只能在getInputStream上获得响应,那么这是否意味着我还没有在getOutputStream上发送任何请求,而只是建立了连接?
请记住,发送请求和发送数据是两种不同的操作。当您调用 getOutputStream 或 getInputStream 时,您可以向服务器发送请求以建立连接。发生握手时,服务器会向您发送连接已建立的确认。然后,在那个时间点,您才准备好发送或接收数据。因此,您不需要调用 getOutputStream 来建立打开流的连接,除非您发出请求的目的是发送数据。url.openConnection()
用外行人的话来说,提出要求相当于给你朋友家打电话说“嘿,如果我过来借用那副把手可以吗?”你的朋友通过说“当然!快来拿吧”。然后,在这一点上,建立连接,你走到你朋友的房子,敲门,要求副把手,然后走回你的房子。getInputStream
使用类似的例子会涉及打电话给你的朋友并说“嘿,我有我欠你的钱,我可以把它寄给你吗”?你的朋友,需要钱,里面生病了,你把它放了这么久,说“当然,来吧,你这个便宜的混蛋”。所以你走到你朋友家,把钱“寄”给他。然后他把你踢出去,你走回你的房子。getOutputStream
现在,继续外行人的例子,让我们看一些异常。如果你打电话给你的朋友,而他不在家,这可能是一个500错误。如果您打电话并收到一条断开的号码消息,因为您的朋友厌倦了您一直借钱,那么找不到404页面。如果您的手机因未付账而死机,则可能是IOException。(注意:此部分可能不是 100% 正确的。它旨在让您大致了解外行人所说的正在发生的事情。
问题 #5:
是的,你是对的,openConnection只是创建一个新的连接对象,但并没有建立它。当您调用 getInputStream 或 getOutputStream 时,将建立连接。
openConnection
创建新的连接对象。From the 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 连接何时关闭?。