J'utilise HTTPURLConnection
pour me connecter à un service Web. Je sais comment utiliser HTTPURLConnection
mais je veux comprendre comment cela fonctionne. En gros, je veux savoir ce qui suit:
HTTPURLConnection
essaie-t-il d'établir une connexion à l'URL donnée?getOutputStream
et getInputStream
en termes simples? Je remarque que lorsque le serveur auquel je tente de me connecter est en panne, je reçois un Exception
sur getOutputStream
. Cela signifie-t-il que HTTPURLConnection
ne commencera à établir une connexion que lorsque j'invoque getOutputStream
? Qu'en est-il de la getInputStream
? Étant donné que je ne peux obtenir que la réponse à getInputStream
, cela signifie-t-il que je n'ai pas encore envoyé de demande à getOutputStream
, mais simplement établir une connexion? Est-ce que HttpURLConnection
revient au serveur pour demander une réponse lorsque j'invoque getInputStream
?openConnection
crée simplement un nouvel objet de connexion mais n'établit pas encore de connexion?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.
En gros, je pense que vous comprenez bien comment cela fonctionne, alors permettez-moi de répéter en termes simples. getOutputStream
ouvre en gros un lien flux, avec l'intention d'écrire des données sur le serveur. Dans l'exemple de code ci-dessus, "message" pourrait ê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 lien flux 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 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 aussi un lien flux, mais l’intention est de lire les données du serveur, pas d’écrire dessus. Si la connexion ou l'ouverture du flux échoue, vous verrez un SocketTimeoutException
.
Comment sur le getInputStream? Étant donné que je ne peux obtenir que la réponse sur getInputStream, cela signifie-t-il que je n'ai pas encore envoyé de requête sur getOutputStream mais que je me connecte simplement?
N'oubliez pas que l'envoi d'une demande et l'envoi de données sont deux opérations différentes. Quand vous invoquez getOutputStream ou getInputStream url.openConnection()
, vous envoyez une demande au serveur pour établir une connexion. Il y a une poignée de main qui se produit lorsque le serveur vous renvoie un accusé de réception établissant 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 ouvrez un flux, à moins que votre objectif de demande ne soit d'envoyer des données.
En termes simples, faire une demande getInputStream
équivaut à passer un coup de téléphone au domicile de votre ami pour lui dire "Hey, est-ce que je peux emprunter cette paire de pinces-étau?" 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 rendez à la maison de votre ami, frappez à la porte, demandez les poignées d’étau et revenez à votre domicile.
Utiliser un exemple similaire pour getOutputStream
impliquerait d'appeler votre ami et de lui dire "Hé, j'ai cet argent que je te dois, puis-je te l'envoyer"? Votre ami, ayant besoin d’argent et malade à l’intérieur de celui que vous avez gardé pendant si longtemps, dit "Bien sûr, allez, bâtard pas cher." Alors vous allez chez votre ami et lui "envoyez" l'argent. Il vous met ensuite à la porte et vous rentrez chez vous.
Maintenant, continuons avec l'exemple du profane, examinons quelques exceptions. Si vous appelez votre ami et qu'il n'était pas à la maison, cela pourrait être une erreur de 500. Si vous avez appelé et reçu un message de numéro déconnecté parce que votre ami est fatigué d'emprunter de l'argent tout le temps, il s'agit d'une page 404 introuvable. Si votre téléphone est mort parce que vous n'avez pas payé la facture, il pourrait s'agir d'une exception IOException. (REMARQUE: cette section peut ne pas être 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 sans l’établir. La connexion est établie lorsque vous appelez getInputStream ou getOutputStream.
openConnection
crée un nouvel objet de connexion. Depuis le RL.openConnection javadocs :
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 lors de leur instanciation.
Question n ° 6 :
Pour mesurer le temps système, j’enroule généralement un code de synchronisation très simple autour du bloc de connexion entier, comme suit:
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 à mes besoins.
Pour plus d'informations sur la fermeture de connexions, pour lesquelles vous n'avez pas posé de question, voir Dans Java quand une connexion d'URL se ferme-t-elle? .
Tim Bray a présenté de manière concise, étape par étape, indiquant qu'openConnection () n'établit pas de connexion réelle. Au lieu de cela, une connexion HTTP réelle n'est pas établie jusqu'à ce que vous appeliez des méthodes telles que getInputStream () ou getOutputStream ().
http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection
Sur quel point HTTPURLConnection essaie-t-il d'établir une connexion à l'URL donnée?
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é.
Sur quel point puis-je savoir que j'ai réussi à établir une connexion?
Lorsque vous appelez getInputStream () ou getOutputStream () ou getResponseCode () sans obtenir d'exception.
Établissez-vous une connexion et envoyez-vous la demande réelle en une seule étape/appel de méthode? De quelle méthode s'agit-il?
Non et aucun.
Pouvez-vous expliquer la fonction de getOutputStream et getInputStream en termes simples?
L'un ou l'autre se connecte d'abord si nécessaire, puis renvoie le flux requis.
Je remarque que lorsque le serveur auquel je tente de me connecter est en panne, je reçois une exception à getOutputStream. Cela signifie-t-il que HTTPURLConnection ne commencera à établir une connexion que lorsque j'appellerai getOutputStream? Comment sur le getInputStream? Étant donné que je ne peux obtenir que la réponse sur getInputStream, cela signifie-t-il que je n'ai pas encore envoyé de requête sur getOutputStream mais que je me connecte simplement? HttpURLConnection retourne-t-il sur le serveur pour demander une réponse lorsque j'invoque getInputStream?
Voir au dessus.
Ai-je raison de dire qu'openConnection crée simplement un nouvel objet de connexion, mais ne crée pas encore de connexion?
Oui.
Comment puis-je mesurer le temps système de lecture et connecter le temps système?
Connecter: prenez le temps qu'il faut à getInoutStream () ou getOutputStream () pour revenir, quel que soit le premier appel. Lecture: temps écoulé entre le début de la première lecture et l’obtention de l’EOS.
Sur quel point HTTPURLConnection essaie-t-il d'établir une connexion avec l'URL donnée?
Cela vaut la peine de préciser, il y a l'instance 'UrlConnection' et ensuite la connexion sous-jacente Tcp/Ip/SSL , 2 concepts différents. L'instance 'UrlConnection' ou 'HttpUrlConnection' est synonyme d'une requête de page HTTP unique et est créée lorsque vous appelez url.openConnection (). Mais si vous faites plusieurs url.openConnection () à partir de l'instance 'url', alors si vous avez de la chance, ils réutiliseront les mêmes socket Tcp/Ip et SSL, ce qui est bien si vous êtes faire beaucoup de demandes de page sur le même serveur, ce qui est particulièrement utile si vous utilisez SSL, où la surcharge liée à l'établissement du socket est très lourde.