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) {
// ...
}
Las primeras 3 respuestas a sus preguntas se enumeran como comentarios en línea, junto a cada método, en el ejemplo HTTP POST anterior.
Desde getOutputStream :
Devuelve una secuencia de salida que escribe en esta conexión.
Básicamente, creo que tienes una buena comprensión de cómo funciona esto, así que permíteme reiterarlo en términos simples. getOutputStream
básicamente abre un flujo de conexión , con la intención de escribir datos en el servidor. En el ejemplo de código anterior, "mensaje" podría ser un comentario que estamos enviando al servidor que representa un comentario dejado en una publicación. Cuando veas getOutputStream
, estás abriendo el flujo de conexión para escribir, pero en realidad no escribes ningún dato hasta que llamas writer.write("message=" + message);
.
Desde getInputStream () :
Devuelve una secuencia de entrada que se lee desde esta conexión abierta. Se puede generar una SocketTimeoutException cuando se lee desde la secuencia de entrada devuelta si el tiempo de espera de lectura caduca antes de que los datos estén disponibles para la lectura.
getInputStream
hace lo contrario Al igual getOutputStream
, también abre un flujo de conexión , pero la intención es leer datos del servidor, no escribir en él. Si la conexión o la apertura de la transmisión falla, verá a SocketTimeoutException
.
¿Qué tal el getInputStream? Como solo puedo obtener la respuesta en getInputStream, ¿significa que todavía no envié ninguna solicitud en getOutputStream sino que simplemente establezco una conexión?
Tenga en cuenta que enviar una solicitud y enviar datos son dos operaciones diferentes. Cuando invoca getOutputStream o getInputStream url.openConnection()
, envía una solicitud al servidor para establecer una conexión. Hay un apretón de manos que ocurre cuando el servidor le envía un reconocimiento de que la conexión está establecida. Es entonces cuando estás preparado para enviar o recibir datos. Por lo tanto, no necesita llamar a getOutputStream para establecer una conexión para abrir una transmisión, a menos que su propósito para realizar la solicitud sea enviar datos.
En términos sencillos, hacer una getInputStream
solicitud es el equivalente a hacer una llamada telefónica a la casa de tu amigo para decir "Oye, ¿está bien si vengo y me prestas ese par de empuñaduras de vicio?" y tu amigo establece el apretón de manos diciendo: "¡Seguro! Ven y tómalo". Luego, en ese punto, se establece la conexión, caminas hacia la casa de tu amigo, tocas la puerta, solicitas los vicios y caminas de regreso a tu casa.
Usar un ejemplo similar getOutputStream
implicaría llamar a tu amigo y decirle "Oye, tengo ese dinero que te debo, ¿puedo enviártelo?" Tu amigo, que necesita dinero y está enfermo por dentro que lo guardaste por tanto tiempo, dice "Claro, ven por tu bastardo barato". Entonces caminas a la casa de tu amigo y le "ENVÍAS" el dinero. Luego te echa y caminas de regreso a tu casa.
Ahora, continuando con el ejemplo del laico, veamos algunas Excepciones. Si llamaste a tu amigo y él no estaba en casa, eso podría ser un error 500. Si llamó y recibió un mensaje de número desconectado porque su amigo está cansado de que le preste dinero todo el tiempo, esa es una página 404 que no se encuentra. Si su teléfono está muerto porque no pagó la factura, podría ser una IOException. (NOTA: es posible que esta sección no sea 100% correcta. Su objetivo es darle una idea general de lo que está sucediendo en términos simples).
Pregunta # 5:
Sí, tiene razón en que openConnection simplemente crea un nuevo objeto de conexión pero no lo establece. La conexión se establece cuando llama a getInputStream o getOutputStream.
openConnection
crea un nuevo objeto de conexión. Desde el URL.openConnection javadocs :
Se abre una nueva conexión cada vez que se llama al método openConnection del controlador de protocolo para esta URL.
La conexión se establece cuando llama a openConnection, y los InputStream, OutputStream, o ambos, se llaman cuando los instancia.
Pregunta # 6 :
Para medir la sobrecarga, generalmente envuelvo un código de tiempo muy simple alrededor del bloque de conexión completo, de esta manera:
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) );
Estoy seguro de que hay métodos más avanzados para medir el tiempo de solicitud y los gastos generales, pero esto generalmente es suficiente para mis necesidades.
Para obtener información sobre cómo cerrar conexiones, sobre las que no preguntó, consulte En Java, ¿cuándo se cierra una conexión URL? .
Returns an output stream that writes to this connection.
yReturns an input stream that reads from this open connection.
. El flujo de salida y el flujo de entrada están separados de la conexión.Tim Bray presentó un conciso paso a paso, indicando que openConnection () no establece una conexión real. Más bien, no se establece una conexión HTTP real hasta que llame a métodos como getInputStream () o getOutputStream ().
http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection
fuente
En el puerto nombrado en la URL si existe, de lo contrario 80 para HTTP y 443 para HTTPS. Creo que esto está documentado.
Cuando llama a getInputStream () o getOutputStream () o getResponseCode () sin obtener una excepción.
No y ninguno
Cualquiera de ellos se conecta primero si es necesario, luego devuelve la secuencia requerida.
Véase más arriba.
Si.
Conectar: tómese el tiempo que tarda getInoutStream () o getOutputStream () en regresar, lo que llame primero. Leer: tiempo desde el comienzo de la primera lectura hasta obtener la EOS.
fuente
¿En qué punto HTTPURLConnection intenta establecer una conexión con la URL dada?
Vale la pena aclarar, está la instancia de 'UrlConnection' y luego está la conexión de socket Tcp / Ip / SSL subyacente , 2 conceptos diferentes. La instancia 'UrlConnection' o 'HttpUrlConnection' es sinónimo de una sola solicitud de página HTTP, y se crea cuando se llama url.openConnection (). Pero si haces múltiples url.openConnection () 's desde la única instancia' url ', entonces, si tienes suerte, reutilizarán el mismo socket Tcp / Ip y cosas de protocolo de enlace SSL ... lo cual es bueno si eres hacer muchas solicitudes de página al mismo servidor, especialmente bueno si está utilizando SSL donde la sobrecarga de establecer el socket es muy alta.
Ver: implementación de HttpURLConnection
fuente
Realicé el ejercicio para capturar el intercambio de paquetes de bajo nivel y descubrí que la conexión de red solo se activa mediante operaciones como getInputStream, getOutputStream, getResponseCode, getResponseMessage, etc.
Aquí está el intercambio de paquetes capturado cuando intento escribir un pequeño programa para cargar un archivo en Dropbox.
A continuación se muestra mi programa de juguetes y anotación.
fuente