web-dev-qa-db-fra.com

Pouvez-vous expliquer le processus de connexion HttpURLConnection?

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:

  • Sur quel point HTTPURLConnection essaie-t-il d'établir une connexion à l'URL donnée?
  • Sur quel point puis-je savoir que j'ai réussi à établir une connexion?
  • É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?
  • Pouvez-vous expliquer la fonction de 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?
  • Ai-je raison de dire que openConnection crée simplement un nouvel objet de connexion mais n'établit pas encore de connexion?
  • Comment puis-je mesurer le temps système de lecture et connecter le temps système?
131
Arci
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? .

179
jmort253

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

14
anonymous

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.

1
user207421

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.

Voir: implémentation de HttpURLConnection

1
Tim Cooper