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) {
// ...
}
Les 3 premières réponses à vos questions sont répertoriées sous forme de commentaires en ligne, à côté de chaque méthode, dans l'exemple HTTP POST ci-dessus.
De getOutputStream :
Renvoie un flux de sortie qui écrit sur cette connexion.
Fondamentalement, je pense que vous avez une bonne compréhension de la façon dont cela fonctionne, alors permettez-moi de répéter en termes simples. getOutputStream
ouvre essentiellement un flux de connexion , avec l'intention d'écrire des données sur le serveur. Dans l'exemple de code ci-dessus, "message" peut être un commentaire que nous envoyons au serveur et qui représente un commentaire laissé sur un message. Lorsque vous voyez getOutputStream
, vous ouvrez le flux de connexion pour l'écriture, mais vous n'écrivez aucune donnée jusqu'à ce que vous appeliez writer.write("message=" + message);
.
De getInputStream () :
Renvoie un flux d'entrée qui lit à partir de cette connexion ouverte. Une exception SocketTimeoutException peut être levée lors de la lecture à partir du flux d'entrée renvoyé si le délai de lecture expire avant que les données ne soient disponibles pour la lecture.
getInputStream
fait le contraire. Comme getOutputStream
, il ouvre également un flux de connexion , mais l'intention est de lire les données du serveur, pas d'y écrire. Si la connexion ou l'ouverture du flux échoue, vous verrez un fichier SocketTimeoutException
.
Qu'en est-il de getInputStream? Étant donné que je ne peux obtenir la réponse qu'à getInputStream, cela signifie-t-il que je n'ai pas encore envoyé de demande à getOutputStream, mais établit simplement une connexion?
Gardez à l'esprit que l'envoi d'une demande et l'envoi de données sont deux opérations différentes. Lorsque vous appelez getOutputStream ou getInputStream url.openConnection()
, vous envoyez une demande au serveur pour établir une connexion. Une poignée de main se produit lorsque le serveur vous renvoie un accusé de réception indiquant que la connexion est établie. C'est à ce moment-là que vous êtes prêt à envoyer ou à recevoir des données. Ainsi, vous n'avez pas besoin d'appeler getOutputStream pour établir une connexion et ouvrir un flux, à moins que votre objectif pour faire la demande soit d'envoyer des données.
En termes simples, faire une getInputStream
demande équivaut à appeler la maison de votre ami pour lui dire "Hé, est-ce que je peux venir et emprunter cette paire de pinces étaux?" et votre ami établit la poignée de main en disant: "Bien sûr! Viens le chercher". Ensuite, à ce moment-là, la connexion est établie, vous vous dirigez vers la maison de votre ami, vous frappez à la porte, vous demandez les étaux et vous retournez chez vous.
Utiliser un exemple similaire pour getOutputStream
impliquerait d'appeler votre ami et de lui dire "Hé, j'ai cet argent que je vous dois, puis-je vous l'envoyer"? Votre ami, qui a besoin d'argent et qui est malade à l'intérieur que vous l'avez gardé si longtemps, dit "Bien sûr, viens sur toi salaud bon marché". Alors vous marchez jusqu'à la maison de votre ami et «POST» l'argent à lui. Il vous expulse ensuite et vous rentrez chez vous.
Maintenant, continuant avec l'exemple du profane, regardons quelques exceptions. Si vous avez appelé votre ami et qu'il n'était pas à la maison, cela pourrait être une erreur 500. Si vous avez appelé et que vous avez reçu un message de numéro déconnecté parce que votre ami est fatigué de vous emprunter de l'argent tout le temps, c'est une page 404 introuvable. Si votre téléphone est mort parce que vous n'avez pas payé la facture, cela pourrait être une IOException. (REMARQUE: cette section n'est peut-être pas correcte à 100%. Elle a pour but de vous donner une idée générale de ce qui se passe en termes simples.)
Question n ° 5:
Oui, vous avez raison, openConnection crée simplement un nouvel objet de connexion mais ne l'établit pas. La connexion est établie lorsque vous appelez getInputStream ou getOutputStream.
openConnection
crée un nouvel objet de connexion. À partir des javadocs URL.openConnection :
Une nouvelle connexion est ouverte à chaque fois en appelant la méthode openConnection du gestionnaire de protocole pour cette URL.
La connexion est établie lorsque vous appelez openConnection, et InputStream, OutputStream ou les deux sont appelés lorsque vous les instanciez.
Question n ° 6 :
Pour mesurer la surcharge, j'enroule généralement un code de synchronisation très simple autour de l'ensemble du bloc de connexion, comme ceci:
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) );
Je suis sûr qu'il existe des méthodes plus avancées pour mesurer le temps de demande et les frais généraux, mais cela suffit généralement pour mes besoins.
Pour plus d'informations sur la fermeture des connexions, que vous n'avez pas posées, consultez En Java, quand une connexion URL se ferme-t-elle? .
Returns an output stream that writes to this connection.
etReturns an input stream that reads from this open connection.
. Le flux de sortie et le flux d'entrée sont séparés de la connexion.Tim Bray a présenté une étape par étape concise, indiquant que openConnection () n'établit pas une connexion réelle. Au contraire, une connexion HTTP réelle n'est pas établie tant que vous n'appelez pas des méthodes telles que getInputStream () ou getOutputStream ().
http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection
la source
Sur le port nommé dans l'URL le cas échéant, sinon 80 pour HTTP et 443 pour HTTPS. Je crois que cela est documenté.
Lorsque vous appelez getInputStream () ou getOutputStream () ou getResponseCode () sans obtenir d'exception.
Non et aucun.
L'un ou l'autre se connecte d'abord si nécessaire, puis renvoie le flux requis.
Voir au dessus.
Oui.
Connect: prenez le temps que getInoutStream () ou getOutputStream () prend pour revenir, selon ce que vous appelez en premier. Lecture: temps écoulé entre le début de la première lecture et l'obtention de l'EOS.
la source
Sur quel point HTTPURLConnection essaie-t-il d'établir une connexion à l'URL donnée?
Cela vaut la peine d'être clarifié, il y a l' instance 'UrlConnection' et puis il y a la connexion de socket Tcp / Ip / SSL sous-jacente , 2 concepts différents. L'instance 'UrlConnection' ou 'HttpUrlConnection' est synonyme d'une seule requête de page HTTP et est créée lorsque vous appelez url.openConnection (). Mais si vous faites plusieurs url.openConnection () à partir de la seule instance 'url', alors si vous avez de la chance, ils réutiliseront le même socket Tcp / Ip et les mêmes trucs de négociation SSL ... ce qui est bien si vous êtes faire beaucoup de requêtes de page sur le même serveur, particulièrement utile si vous utilisez SSL où la surcharge liée à l'établissement du socket est très élevée.
Voir: Implémentation HttpURLConnection
la source
J'ai parcouru l'exercice pour capturer l'échange de paquets de bas niveau et j'ai découvert que la connexion réseau n'est déclenchée que par des opérations telles que getInputStream, getOutputStream, getResponseCode, getResponseMessage, etc.
Voici l'échange de paquets capturé lorsque j'essaie d'écrire un petit programme pour télécharger un fichier sur Dropbox.
Ci-dessous mon programme de jouets et mon annotation
la source