Table des matières
Comprendre les connexions persistantes HTTP (Keep-Alive)
Malets de malentendus communs et analyse du protocole
1. Utilisation abusive de la version du protocole HTTP
2. Connexion: l'effet de l'en-tête de réponse proche
3. L'importance du support côté serveur
Gérer correctement les réponses HTTP et les connexions persistantes
Maison Java javaDidacticiel Une compréhension approfondie des connexions persistantes HTTP: politiques et pratiques pour envoyer plusieurs demandes sur la même prise

Une compréhension approfondie des connexions persistantes HTTP: politiques et pratiques pour envoyer plusieurs demandes sur la même prise

Sep 21, 2025 pm 01:51 PM

Une compréhension approfondie des connexions persistantes HTTP: politiques et pratiques pour envoyer plusieurs demandes sur la même prise

Cet article explore en profondeur le mécanisme d'envoi de plusieurs demandes HTTP sur la même prise TCP, à savoir la connexion persistante HTTP (Keep-Alive). L'article clarifie la différence entre les protocoles HTTP / 1.x et HTTP / 2, souligne l'importance de la prise en charge côté serveur pour les connexions persistantes et comment gérer correctement la connexion: fermer les en-têtes de réponse. En analysant les erreurs courantes et en fournissant les meilleures pratiques, nous visons à aider les développeurs à construire des clients HTTP efficaces et robustes.

Comprendre les connexions persistantes HTTP (Keep-Alive)

Les connexions persistantes HTTP, également connues sous le nom de HTTP Keep-Alive, permettent aux clients d'envoyer et de recevoir plusieurs demandes et réponses HTTP sur la même connexion TCP sans avoir à rétablir une nouvelle connexion pour chaque demande. Cela réduit considérablement les frais généraux de la poignée de main TCP et du démarrage lent, améliorant ainsi les performances et l'efficacité. Dans HTTP / 1.1, les connexions persistantes sont le comportement par défaut, sauf si la connexion: Close est explicitement spécifiée. HTTP / 2 va plus loin, traitant plusieurs demandes et réponses simultanément sur une seule connexion par multiplexage.

Cependant, l'implémentation du client envoie plusieurs demandes sur le même socket nécessite la bonne coopération entre le client et le serveur. Le client envoie la connexion: Keep-Alive n'est qu'une demande, et le serveur a le droit de choisir de l'accepter.

Malets de malentendus communs et analyse du protocole

Lorsque vous essayez de mettre en œuvre des connexions persistantes, les développeurs rencontrent souvent des malentendus:

1. Utilisation abusive de la version du protocole HTTP

Le code d'origine essaie d'envoyer une demande à l'aide de la chaîne de protocole HTTP / 2:

 "Get /" x "http / 2 \ r \ n"

Il s'agit d'une idée fausse commune. Http / 2 et http / 1.x sont deux protocoles complètement différents:

  • HTTP / 1.X est un protocole basé sur le texte, et chaque paire de requête / réponse est généralement traitée séquentiellement.
  • HTTP / 2 est un protocole binaire qui introduit des fonctionnalités avancées telles que le multiplexage, la compression de la tête et la poussée du serveur. Il nécessite des mises à niveau de protocole pendant la phase de poignée de main TLS par le biais de la négociation du protocole de couche d'application (ALPN), plutôt que de simplement déclarer HTTP / 2 dans la ligne de demande. Le remplacement de HTTP / 1.1 par HTTP / 2 ne permet pas directement au serveur HTTP / 1.x de comprendre les demandes HTTP / 2, mais conduira plutôt à des erreurs de protocole. Pour les serveurs HTTP / 1.x, HTTP / 1.1 ou HTTP / 1.0 doivent toujours être utilisés.

2. Connexion: l'effet de l'en-tête de réponse proche

Lorsque le serveur contient la connexion: fermer dans l'en-tête de réponse, il demande explicitement au client de fermer la connexion TCP après avoir reçu la réponse actuelle. Cela signifie que même si le client envoie une connexion: conserver dans la demande, la décision du serveur est toujours définitive.

Dans l'exemple de sortie:

 Http / 1.1 200 ok
Longueur du contenu: 2
Type de contenu: texte / simple
Connexion: fermer
Accept-glages: aucun

Le serveur renvoie explicitement la connexion: fermer, donc après avoir envoyé le corps de réponse actuel, il ferme la connexion de socket. Après avoir lu toutes les données, le lecteur.readline () du client retournera NULL car la connexion est fermée, ce qui fait que la boucle se termine et les demandes ultérieures ne peuvent pas être envoyées sur le même socket.

3. L'importance du support côté serveur

Le cœur de l'implémentation de connexions persistantes est de savoir si le serveur prend en charge et le permet. En particulier sur les appareils liés aux ressources, tels que les microcontrôleurs ESP32, leur pile HTTP peut choisir de ne pas implémenter ou activer des connexions persistantes afin de simplifier et d'économiser des ressources. Dans ce cas, le serveur peut insister sur la fermeture de la connexion, quelle que soit la façon dont le client demande la connexion: Keep-Alive.

Gérer correctement les réponses HTTP et les connexions persistantes

Afin de gérer correctement plusieurs demandes HTTP sur la même prise, le client a besoin:

  1. Envoyer l'en-tête de demande HTTP / 1.1 correct : assurez-vous que la ligne de demande utilise HTTP / 1.1 et comprend l'en-tête hôte. Si vous vous attendez à une connexion persistante, vous pouvez explicitement envoyer une connexion: Keep-Alive, mais ce n'est pas obligatoire, car HTTP / 1.1 est une connexion persistante par défaut.

     String request = string.format (
        "Get /% s http / 1.1 \ r \ n" // en utilisant http / 1.1
          "Hôte:% s \ r \ n"
          "Connexion: Keep-alive \ r \ n" // demande explicitement une connexion persistante "\ r \ n",
        x, nom d'hôte
    ));
    output.write (demande);
    output.flush ();
  2. La lecture correcte de la réponse HTTP : c'est l'étape la plus critique. La réponse HTTP se compose d'une ligne de statut, d'un en-tête de réponse et d'un corps de réponse. Lors de la lecture de la réponse, vous ne pouvez pas simplement boucler via readLine () jusqu'à ce que vous reveniez null, car cela bloquera jusqu'à ce que la connexion soit fermée. La bonne façon de le faire est:

    • Lisez l'en-tête de réponse ligne par ligne : jusqu'à ce qu'une ligne vide (\ r \ n) soit rencontrée, l'en-tête se termine.
    • En-têtes de réponse d'analyse : en particulier, la longueur du contenu et les en-têtes de connexion.
      • Si la longueur de contenu existe, le corps de réponse du nombre spécifié d'octets est lu.
      • Si le transfert de transfert: le morceau existe, le corps de réponse est lu par la règle de codage de section.
      • Résoudre l'en-tête de la connexion: Si le serveur répond à la connexion: Fermer, le client doit fermer la prise après avoir lu la réponse actuelle. Si vous répondez à la connexion: Keep-Alive (ou non spécifié, HTTP / 1.1 par défaut), vous pouvez essayer d'envoyer la demande suivante.

Exemple: une logique de lecture réactive plus robuste (version simplifiée, non entièrement analysée pour tous les détails HTTP)

L'extrait de code suivant montre comment lire une réponse et décider de continuer en fonction de l'en-tête de connexion:

 importer java.io. *;
import java.net.socket;
Importer java.net.url;
import java.util.hashmap;
importation java.util.map;

classe publique httpClientRobust {

    prise à douille privée;
    Sortie privée privée;
    lecteur privé BufferedReader;
    nom d'hôte de chaîne privée;
    booléen privé keepalive = true; // Supposons que cela prévoit initialement la connexion publique httpClientRobust () lève ioException {
        Url url = nouvelle URL ("http://192.168.178.56"); // remplace par votre IP ESP32
        hostname = url.gethost ();
        int port = 80;

        socket = new socket (nom d'hôte, port);
        output = new printwriter (socket.getOutputStream ());
        Reader = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
    }

    public void SendAndReceive (String Path) lève IOException, InterruptedException {
        si (! keepalive) {
            System.out.println ("Connexion clôturée par serveur. Impossible d'envoyer plus de demandes sur cette prise.");
            retour;
        }

        String request = string.format (
            "Get /% s http / 1.1 \ r \ n"
              "Hôte:% s \ r \ n"
              "Connexion: Keep-Alive \ r \ n" // Le client demande pour garder la connexion "\ r \ n",
            chemin, nom d'hôte
        ));

        System.out.println ("--- Envoi de la demande ---");
        System.out.println (demande);
        output.write (demande);
        output.flush ();

        System.out.println ("--- Réponse de réception ---");
        Map <string string> headers = new hashmap  ();
        Ligne de chaîne;
        int contentLength = -1;

        // Lire la ligne d'état Line = Reader.Readline ();
        if (line == null) {
            System.out.println ("Server Closed Connection prématurément.");
            keepalive = false;
            retour;
        }
        System.out.println (ligne); // Imprimer la ligne d'état // Lire et analyser l'en-tête de réponse while ((line = reader.readline ())! = Null &&! Line.isempty ()) {
            System.out.println (ligne);
            int colonIndex = line.indexof (':');
            if (colonindex> 0) {
                String Headhername = Line.SubString (0, ColonIndex) .trim ();
                String Herevalue = Line.SubString (ColonIndex 1) .trim ();
                en-têtes.put (headername.tolowercase (), hiervalue);
            }
        }

        // Vérifiez l'en-tête de connexion if ("close" .equalsIgnoreCase (en-têtes.get ("connexion"))) {
            keepalive = false;
            System.out.println ("Server demandé à fermer la connexion.");
        }

        // Vérifiez la longueur du contenu
        if (headers.ContainsKey ("Content-Length")) {
            essayer {
                contentLength = Integer.ParseInt (en-têtes.get ("Content-Length"));
                System.out.println ("Content-Length:" ContentLength);
                // Lire le corps de réponse char [] buffer = new char [contentLength];
                int byTesRead = 0;
                while (bytesRead <tentlengle int r reader.read bytesread contentlength if system.out.println connexion ferm avant de lire le contenu complet. keepalive="false;" casser new string catch e system.err.println longueur non valide. autre s n a pas et qu entendu que serveur explicitement arr lisez ensuite jusqu ce la soit cela ne dans les connexions persistantes. fin doit jug par du ou codage transfert. pour cas o envoie connexion: fermer cet exemple vous pouvez continuer sp se ferme eof. stringbuilder responsebody="new" while reader.readline null reader.ready bloquer> 0) {
                System.out.println ("Corps de réponse:" ResponseBody.ToString (). Trim ());
            }
        }

        si (! keepalive) {
            fermer();
        }
    }

    public void close () lève ioException {
        if (socket! = null &&! socket.isclosed ()) {
            socket.close ();
            System.out.println ("Socket fermé.");
        }
    }

    public static void main (String [] args) lance ioException, InterruptedException {
        HttpClientRobust client = null;
        essayer {
            client = nouveau httpClientRobust ();
            pour (int i = 1; i <p> <strong>Notes:</strong></p>
<ul>
<li> Reader.read (Buffer, BytesRead, ContentLength - BytesRead) dans l'exemple ci-dessus est la bonne façon de lire un corps de réponse de longueur fixe.</li>
<li> Reader.ready () peut ne pas être suffisamment fiable lors de la lecture du corps de réponse, car les données peuvent toujours être en transit mais n'ont pas encore atteint le tampon. Les clients HTTP plus robustes nécessitent une logique plus complexe pour gérer divers codages de transfert (tels que les transferts en morceaux) et des délais d'attente.</li>
<li> Si le serveur répond à la connexion: Close, l'indicateur Keepalive sera défini sur False et les demandes suivantes ne seront pas envoyées.</li>
</ul>
<h3> Résumé et meilleures pratiques</h3>
<ol>
<li><p> <strong>Comprendre les différences de protocole</strong> : HTTP / 1.x et HTTP / 2 sont des protocoles différents. Ne confondez pas leur utilisation. Pour la plupart des services Web simples, HTTP / 1.1 est suffisant et sa connexion persistante est le comportement par défaut.</p></li>
<li><p> <strong>Respectez l'intention du serveur</strong> : le client demande la connexion: Keep-Alive Juste une suggestion, et l'en-tête de réponse de connexion du serveur (en particulier la connexion: clôture) a la décision finale. Vérifiez toujours l'en-tête de réponse du serveur.</p></li>
<li><p> <strong>Analyser correctement la réponse</strong> : ne comptez pas sur la boucle readline () jusqu'à ce qu'elle revienne nul pour déterminer la fin de la réponse, ce qui est mauvais pour les connexions persistantes. La longueur du contenu ou le codage de transfert doit être analysée pour déterminer les limites du corps de réponse.</p></li>
<li><p> <strong>Considérez les capacités du serveur</strong> : en particulier pour les appareils intégrés (tels que ESP32), sa pile HTTP peut avoir une fonctionnalité limitée. Si le serveur ne prend pas en charge les connexions persistantes, le client doit être prêt à établir une nouvelle connexion pour chaque demande.</p></li>
<li>
<p> <strong>Utilisez des bibliothèques clients HTTP matures</strong> : pour une communication HTTP complexe, il est fortement recommandé d'utiliser Java intégrée Java.net.httpurlconnection ou des bibliothèques tierces telles que Apache HttpClient, OKHTTP, etc. etc., simplifiant considérablement le travail de développement. Par exemple:</p>
<pre class="brush:php;toolbar:false"> importer java.net.uri;
Importer java.net.http.httpclient;
import java.net.http.httprequest;
Importer java.net.http.httpResponse;
Importer Java.Time.Duration;

classe publique modernehttpclientExample {
    public static void main (String [] args) lève une exception {
        Httpclient client = httpclient.newbuilder ()
                .version (httpclient.version.http_1_1) // Utilisez clairement http / 1.1
                .ConnectTimeout (durée.
                .construire();

        pour (int i = 1; i  réponse = client.send (request, httpResponse.bodyHandlers.ofString ());

            System.out.println ("demande" i "vers /" path);
            System.out.println ("Code d'état:" Response.Staturcode ());
            System.out.println ("Corps de réponse:" Response.Body ());
            System.out.println ("En-tête de connexion:" Response.Headers (). FirstValue ("Connection"). Orelse ("N / A"));

            // La bibliothèque HttpClient gère automatiquement les connexions persistantes. Si le serveur renvoie la connexion: fermer, il ferme la connexion actuelle et établit une nouvelle connexion la prochaine fois qu'elle le demande.
            Thread.Sleep (1000);
        }
    }
}

En suivant ces principes, les développeurs peuvent gérer plus efficacement les connexions HTTP et créer des applications Web haute performance et fiables.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Stock Market GPT

Stock Market GPT

Recherche d'investissement basée sur l'IA pour des décisions plus intelligentes

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment créer un fichier en java Comment créer un fichier en java Sep 21, 2025 am 03:54 AM

UseFile.CreateEnewFile () toCreateaFileOnlyiFitDoOesn’texist, EvitingoverWriting; 2.Preferfiles.CreateFile () FromNio.2Formodern, SafeFilecreationThatFailSiftheFileExists; 3.UseFileWriterorPrintwriterWistereAdMedimMedimate

Comment ajouter un fichier JAR au cours de classe en Java? Comment ajouter un fichier JAR au cours de classe en Java? Sep 21, 2025 am 05:09 AM

Utilisez le paramètre -cp pour ajouter le pot au ClassPath, afin que le JVM puisse charger ses classes et ressources internes, telles que Java-Cplibrary.jarcom.example.main, qui prend en charge plusieurs pots séparés par semi-colons ou couleurs, et peut également être configuré via des variables d'environnement de ClassPath Variables ou Manifest.mf.

Comment implémenter une interface dans Java? Comment implémenter une interface dans Java? Sep 18, 2025 am 05:31 AM

Utilisez le mot-clé Implements pour implémenter l'interface. La classe doit fournir des implémentations spécifiques de toutes les méthodes dans l'interface. Il prend en charge plusieurs interfaces et est séparé par des virgules pour s'assurer que les méthodes sont publiques. Les méthodes par défaut et statiques après Java 8 n'ont pas besoin d'être réécrites.

Construire des applications extensibles avec l'interface de service de service Java (SPI) Construire des applications extensibles avec l'interface de service de service Java (SPI) Sep 21, 2025 am 03:50 AM

Javaspi est un mécanisme de découverte de service intégré dans JDK et met en œuvre une expansion dynamique orientée vers l'interface via ServiceLoader. 1. Définissez l'interface de service et créez un fichier nommé avec le nom complet de l'interface sous Meta-Inf / Services /, et écrivez le nom entièrement qualifié de la classe d'implémentation; 2. Utilisez ServiceLoader.Load () pour charger la classe d'implémentation, et le JVM lira automatiquement la configuration et l'instanciera; 3. Le contrat d'interface doit être clarifié lors de la conception, de la priorité de support et du chargement conditionnel et fournit une implémentation par défaut; 4. Les scénarios d'application incluent l'accès au canal multi-paiement et la vérification du plug-in; 5. Faites attention aux performances, à ClassPath, à l'isolement des exceptions, à la sécurité des fils et à la compatibilité des versions; 6. Dans Java9, la fourniture peut être utilisée en combinaison avec des systèmes de modules.

Une compréhension approfondie des connexions persistantes HTTP: politiques et pratiques pour envoyer plusieurs demandes sur la même prise Une compréhension approfondie des connexions persistantes HTTP: politiques et pratiques pour envoyer plusieurs demandes sur la même prise Sep 21, 2025 pm 01:51 PM

Cet article explore en profondeur le mécanisme d'envoi de plusieurs demandes HTTP sur la même prise TCP, à savoir la connexion persistante HTTP (Keep-Alive). L'article clarifie la différence entre les protocoles HTTP / 1.x et HTTP / 2, souligne l'importance de la prise en charge côté serveur pour les connexions persistantes et comment gérer correctement la connexion: fermer les en-têtes de réponse. En analysant les erreurs courantes et en fournissant les meilleures pratiques, nous visons à aider les développeurs à construire des clients HTTP efficaces et robustes.

Tutoriel Java: comment aplatir une liste de table imbriquée et remplir ses éléments dans un tableau Tutoriel Java: comment aplatir une liste de table imbriquée et remplir ses éléments dans un tableau Sep 18, 2025 am 07:24 AM

Ce didacticiel détaille comment traiter efficacement les listes de table imbriquées contenant d'autres listes de tableaux en Java et fusionner tous ses éléments internes en un seul tableau. L'article fournira deux solutions de base grâce à l'opération FlatMap de l'API Java 8 Stream: aplatissant d'abord une liste, puis remplissant le tableau, et créant directement un nouveau tableau pour répondre aux besoins de différents scénarios.

Comment lire un fichier de propriétés en Java? Comment lire un fichier de propriétés en Java? Sep 16, 2025 am 05:01 AM

Utilisez la classe Properties pour lire facilement les fichiers de configuration Java. 1. Mettez Config.Properties dans le répertoire de ressources, chargez-le via getClassOader (). GetResourceAsStream () et appelez la méthode Load () pour lire la configuration de la base de données. 2. Si le fichier est dans un chemin externe, utilisez FileInputStream pour le charger. 3. Utilisez GetProperty (Key, DefaultValue) pour gérer les clés manquantes et fournir des valeurs par défaut pour garantir la gestion des exceptions et la vérification des entrées.

Comprendre les génériques Java et les jokers Comprendre les génériques Java et les jokers Sep 20, 2025 am 01:58 AM

JavagenerricsprovideCompile-TimetypePesafetyAndeliminateStingByAllowingTypeParameTersersonClasses, Interfaces et Methods; Wildcards (?,

See all articles