

   Cette section décrit le flot de message et la sémantique de chaque type de
   message. (Les détails sur la représentation exacte de chaque message
   apparaît dans Section 53.7.) Il existe
   plusieurs sous-protocoles différents dépendant de l'état de la
   connexion : démarrage, requête, appel de fonction,
   COPY, et fin. Il existe aussi plusieurs cas spéciaux pour
   les opérations asynchrones (incluant les réponses aux notifications et les
   annulations de commande), qui peuvent survenir à tout moment après la phase
   de démarrage.
  
    Pour commencer une session, un client ouvre une connexion au serveur et
    envoie un message de démarrage. Ce message inclut les noms de l'utilisateur
    et de la base de données sur laquelle l'utilisateur souhaite se
    connecter ; il identifie aussi la version particulière du protocole à
    utiliser. (En option, le message de démarrage peut inclure différentes
    configurations de paramètres.) Le serveur utilise ensuite cette information
    et le contenu des fichiers de configuration (tels que
    pg_hba.conf) pour déterminer si la connexion est
    acceptable et le type d'authentification requis (si c'est le cas).
   
Ensuite, le serveur envoie un message approprié de demande d'authentification, auquel le client doit répondre avec un message approprié de réponse d'authentification (par exemple, avec un mot de passe). Pour toutes les méthodes d'authentification, sauf GSSAPI, SSPI et SASL, il existe au moins une requête et une réponse. Pour certaines méthodes, aucune réponse n'est nécessaire, et donc aucune demande d'authentification n'arrive. Pour les méthodes GSSAPI, SSPI et SASL, plusieurs échanges de paquets pourraient être nécessaires pour terminer l'authentification.
Le cycle d'authentification se termine avec le serveur rejetant la tentative de connexion (message ErrorResponse), ou renvoyant le message AuthenticationOk.
Dans cette phase, les messages possibles provenant du serveur sont :
La demande de connexion a été rejetée. Le serveur ferme immédiatement la connexion.
L'échange d'authentification s'est terminé avec succès.
Le client doit maintenant prendre part à un dialogue d'authentification Kerberos V5 (qui n'est pas décrit ici, et fait partie de la spécification Kerberos) avec le serveur. Si ce dialogue réussit, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse. Ceci n'est plus accepté.
Le client doit maintenant envoyer un message PasswordMessage contenant le mot de passe en clair. Si le mot de passe est bon, le serveur répond avec un message AuthenticationOk, sinon il répond avec un message ErrorResponse.
        Le client doit maintenant envoyer un message PasswordMessage contenant
        le mot de passe (avec le nom de l'utilisateur) chiffré avec MD5, puis
        chiffré de nouveau en utilisant le sel aléatoire de quatre octets
        indiqué dans le message AuthenticationMD5Password. S'il s'agit du bon
        mot de passe, le serveur répond avec un message AuthenticationOk, sinon
        il répond avec nu message ErrorResponse. Le message PasswordMessage réel
        peut être calculé en SQL avec un concat('md5',
        md5(concat(md5(concat(motdepasse, nomdutilisateur)),
        selaléatoire))).  (Gardez en tête que la fonction
        md5() renvoie le résultat sous la forme d'une
        chaîne hexadécimale.)
       
Le client doit maintenant initier une négociation GSSAPI. Le client enverra un message GSSResponse avec la première partie du flux de données GSSAPI en réponse à cela. Si plusieurs messages sont nécessaires, le serveur répondra avec AuthenticationGSSContinue.
Le client doit maintenant initier une négociation SSPI. Le client enverra un message GSSResponse avec la première partie du flux de données SSPI en réponse à cela. Si plusieurs messages sont nécessaires, le serveur répondra avec AuthenticationGSSContinue.
Ce message contient les données de réponse de l'étape précédente de la négociation GSSAPI ou SSPI (AuthenticationGSS, AuthenticationSSPI ou un AuthenticationGSSContinue précédent). Si les données GSSAPI ou SSPI de ce message indique que plus de données sont nécessaires pour terminer l'authentification, le client doit envoyer les données dans un autre message GSSResponse. Si l'authentification GSSAPI ou SSPI est terminée par ce message, le serveur enverra ensuite un message AuthenticationOk pour indiquer une authentification réussie ou un message ErrorResponse pour indiquer un échec.
Le client doit maintenant initier une négociation SASL, en utilisant un des mécanismes SASL listés dans le message. Le client doit envoyer un message SASLInitialResponse avec le nom du mécanisme sélectionné, et la première partie du flux de données SASL en réponse à ceci. Si plus de messages sont nécessaires, le serveur répondra avec un message AuthenticationSASLContinue. Voir Section 53.3 pour les détails.
Ce message contient des données de challenge provenant des étapes précédentes de la négociation SASL (AuthenticationSASL, ou d'un précédent AuthenticationSASLContinue). Le client doit répondre avec un message SASLResponse.
L'authentification SASL a terminé avec les données supplémentaires spécifiques du mécanisme pour le client. Le serveur enverra ensuite le message AuthenticationOk pour indiquer une authentification réussie ou un message ErrorResponse pour indiquer un échec. Ce message est envoyé uniquement si le mécanisme SASL indique que des données supplémentaires doivent être envoyées du serveur au client à la fin.
        Le serveur n'accepte pas la version mineure du protocole réclamée par le
        client, mais accepte une version plus ancienne du protocole ; ce
        message indique la version mineure la plus haute que le serveur accepté.
        Ce message sera aussi envoyé si le client a demandé des options non
        acceptées du protocole (par exemple commençant avec
        _pq_.) dans le paquet de démarrage. Ce message sera
        suivi par un message ErrorResponse ou par un message indiquant le succès
        ou l'échec de l'authentification.
       
Si le client n'accepte pas la méthode d'authentification demandée par le client, il doit immédiatement fermer la connexion.
Après avoir reçu le message AuthenticationOk, le client doit attendre plus de messages du serveur. Dans cette phase, un processus backend est démarré, et le client est juste un partenaire intéressé. Il est toujours possible que la demande de démarrage échoue (ErrorResponse) ou que le serveur décline le support de la version mineure demandée du protocole (NegotiateProtocolVersion), mais dans un cas normal, le backend enverra quelques messages ParameterStatus, BackendKeyData et enfin ReadyForQuery.
Lors de cette phase, le backend tentera d'appliquer toute configuration supplémentaire de paramètre d'exécution donnée lors du message de démarrage. EN cas de succès, ces valeurs deviennent les valeurs par défaut de la session. Une erreur cause un message ErrorResponse puis quitte.
Les messages possibles provenant du backend dans cette phase sont :
Ce message fournit des données de clé secrète que le client doit conserver s'il souhaite être capable d'annuler des requêtes plus tard. Le client ne doit pas répondre à ce message mais doit continuer à attendre un message ReadyForQuery.
Ce message informe le client sur la configuration actuelle (initiale) d'un paramètre serveur, tel que client_encoding ou datestyle. Le client peut ignorer ce message, ou enregistrer la configuration pour une utilisation ultérieure ; voir Section 53.2.7 pour plus de détails. Le client ne doit pas répondre à ce message, mais doit continuer à attendre un message ReadyForQuery.
Le démarrage est terminé. Le client peut maintenant exécuter des commandes.
Le démarrage a échoué. La connexion est fermée après l'envoi de ce message.
Un message d'avertissement a été envoyé. Le client doit afficher le message mais continuer à attendre des messages ReadyForQuery ou ErrorResponse.
Le message ReadyForQuery est le même que le backend enverra après chaque cycle de commande. Suivant les besoins du client, il est raisonnable de considérer le message ReadyForQuery comme débutant un cycle de commande ou de le considérer comme terminant la phase de démarrage et chaque cycle de commandes suivant.
Un cycle de requête simple est initié par le client envoyant un message Query au backend. The message inclut une commande SQL (ou des commandes) exprimée sous la forme d'une chaîne de caractères. Le backend envoie alors une ou plusieurs réponses suivant le contenu de la chaîne de texte, et termine par un message ReadyForQuery. Ce dernier message informe le client qu'il peut envoyer une nouvelle commande. (Il n'est pas absolument nécessaire que le client attende le message ReadyForQuery avant de lancer une autre commande, mais le client prend alors la responsabilité de comprendre ce qu'il se passe si la commande précédente échoue et que les commandes suivantes déjà lancées réussissent.)
Les messages de réponse possibles du backend sont :
Une commande SQL terminée normalement.
Le backend est prêt à copier des données du client vers une table ; voir Section 53.2.6.
Le backend est prêt à copier les données d'une table vers le client ; voir Section 53.2.6.
        Indique que les lignes sont prêtes à être renvoyées en réponse à une
        requête SELECT, FETCH, etc. Le
        contenu de ce message décrit la disposition des colonnes pour les
        lignes. Ceci sera suivi par un message DataRow pour chaque ligne
        renvoyée au client.
       
        Un des ensembles de lignes renvoyés par une requête
        SELECT, FETCH, etc.
       
Une chaîne a été reconnue à la place d'une requête.
Une erreur est survenue.
Le traitement de la requête est terminé. Un message séparé est envoyé pour l'indiquer parce que la chaîne de texte pourrait contenir plusieurs commandes SQL. (Le message CommandComplete marque la fin du traitement d'une commande SQL, et non pas de la chaîne complète.) Le message ReadyForQuery sera toujours envoyé, que le traitement se termine avec succès ou avec échec.
Un message d'avertissement a été envoyé en relation à la requête. Les avertissements sont en plus des autres réponses, autrement dit le backend continuera de traiter la commande.
    La réponse à une requête SELECT (ou autres requêtes qui
    renvoient des ensembles de lignes, tels que EXPLAIN ou
    SHOW), consiste normalement en des messages
    RowDescription, zéro ou plusieurs messages DataRow, et enfin un message
    CommandComplete. COPY vers ou à partir du client fait
    appel à un protocole spécial décrit dans Section 53.2.6.
    Tous les autres types de requêtes produisent normalement seulement un
    message CommandComplete.
   
Comme une chaîne de texte peut contenir plusieurs requêtes (séparées par des points-virgules), il pourrait y avoir plusieurs séquences de réponses avant que le backend finisse le traitement de la chaîne. Le message ReadyForQuery est lancé quand la chaîne entière a été traitée et que le backend est prêt à accepter une nouvelle chaîne de texte.
Si une chaîne de caractères complètement vide est reçue (aucun contenu autre que les espaces blancs), la réponse est EmptyQueryResponse suivi par ReadyForQuery.
Au cas où une erreur survient, le message ErrorResponse est envoyé suivi d'un message ReadyForQuery. Tous les autres traitement de chaîne de texte sont annulés par le message ErrorResponse (même s'il reste des requêtes dans la chaîne). Notez que ceci pourrait survenir au milieu de la séquence de messages générés par une requête individuel.
    Dans le mode simple requête, le format de valeurs récupérées est toujours du
    texte, sauf quand la commande données est un FETCH à
    partir d'un curseur déclaré avec l'option BINARY. Dans ce
    cas, les valeurs récupérées sont dans un format binaire. Les codes format
    donnés dans le message RowDescription indiquent le format utilisé.
   
Un client doit être préparé pour accepter des messages ErrorResponse et NoticeResponse à chaque fois qu'il est attendu d'autres types de message. Voir aussi Section 53.2.7 pour les messages que le backend pourrait générer à cause d'événements externes.
Une pratique recommandée est de coder des clients dans un style machine d'états qui acceptera tout type de message à tout moment où cela aurait du sens, plutôt que de coder des suppositions sur la séquence exacte des messages.
Quand un message simple Query contient plus d'une requête SQL (séparé par des points-virgules), ces requêtes sont exécutées comme une seule transaction, sauf si des commandes de contrôle de transaction explicites sont inclus pour forcer un comportement différent. Par exemple, si le message contient :
INSERT INTO mytable VALUES(1); SELECT 1/0; INSERT INTO mytable VALUES(2);
     alors une erreur de division par zéro dans la requête
     SELECT forcera l'annulation du premier
     INSERT. De plus, comme l'exécution du message est
     abandonnée à la première erreur, le deuxième INSERT
     n'est jamais tenté.
    
Si le message contient à la place :
BEGIN; INSERT INTO mytable VALUES(1); COMMIT; INSERT INTO mytable VALUES(2); SELECT 1/0;
     alors le premier INSERT est validé par la commande
     COMMIT explicite. Le deuxième INSERT
     et le SELECT sont toujours traités comme une seule
     transaction, donc l'échec de division par zéro annulera le second
     INSERT, mais pas le premier.
    
Ce comportement est implémenté en exécutant les requêtes dans un message message multi-requêtes dans un bloc de transaction implicite sauf s'il existe un bloc de transaction explicite pour leur exécution. La principale différence entre un bloc de transaction implicite et un bloc standard est qu'un bloc implicite est fermé automatiquement à la fin d'un message Query, soit par une validation implicite s'il n'y a pas d'erreur, soit par une annulation implicite s'il y avait une erreur. Ceci est similaire à la validation ou à l'annulation implicite qui survient pour une requête exécutée par elle-même (quand elle n'est pas dans un bloc de transaction).
     Si la session est déjà dans un bloc de transaction, en résultat d'un
     BEGIN dans un message précédent, alors le message Query
     continue simplement ce bloc de transaction, si le message contient une ou
     plusieurs requêtes. Néanmoins, si le message Query contient un
     COMMIT ou un ROLLBACK fermant le bloc
     de transaction existant, alors toutes les requêtes suivantes sont exécutées
     dans un bloc de transaction explicite.  Inversement, si un
     BEGIN apparaît dans un message Query multi-requêtes,
     alors il démarre un bloc de transaction standard qui sera uniquement
     terminé par un COMMIT ou ROLLBACK
     explicite, apparaissant soit dans ce message Query soit dans un message
     suivant. Si le BEGIN suit certaines requêtes qui ont
     été exécutées sous la forme d'un bloc de transaction implicite, ces
     requêtes ne sont pas immédiatement validées ; en effet, elles sont
     inclues rétroactivement dans le nouveau bloc de transaction standard.
    
     Un COMMIT ou un ROLLBACK apparaissant
     dans un bloc de transaction implicite est exécuté de façon normale, fermant
     le bloc implicite ; néanmoins, un message d'avertissement sera renvoyé
     car un COMMIT ou un ROLLBACK sans
     BEGIN pourrait être une erreur. Si des requêtes suivent,
     un nouveau bloc de transaction implicite sera démarré pour elles.
    
Les savepoints ne sont pas autorisés dans un bloc de transaction implicite car elles pourraient entrer en conflit avec le comportement de fermeture automatique du bloc en cas d'erreur.
Rappelez-vous que, quelque soient les commandes de contrôle des transactions présentes, l'exécution d'un message Query s'arrête à la première erreur. Donc sur cet exemple :
BEGIN; SELECT 1/0; ROLLBACK;
     dans un seul message Query, la session sera laissée à l'intérieur d'un bloc
     de transaction standard en échec car ROLLBACK n'est pas
     atteint après l'erreur de division par zéro. Un autre
     ROLLBACK sera nécessaire pour restaurer la session dans
     un état utilisable.
    
Un autre comportement à noter est que l'analyse lexicale et syntaxique est réalisée sur la chaîne de caractères entière avant qu'une seule requête ne soit exécutée. De ce fait, les erreurs simples (telle qu'un mot clé mal orthographié) dans des requêtes ultérieures peuvent empêcher l'exécution des requêtes. Ceci est habituellement invisible pour les utilisateurs car les requêtes vont de toute façon être intégralement annulées quand elles font partie d'un bloc de transaction implicite. Cependant, cela peut se voir lors d'une tentative sur plusieurs transactions dans un message Query multi-requêtes. Par exemple, si une faute est intégrée à l'exemple précédent comme ceci :
BEGIN; INSERT INTO mytable VALUES(1); COMMIT; INSERT INTO mytable VALUES(2); SELCT 1/0;
     alors aucune des requêtes ne sera exécutée, résultant en une différence
     visible, à savoir que le premier INSERT n'est pas
     validé. Les erreurs détectées lors de l'analyse sémantique ou plus tard,
     comme une table ou une colonne mal nommée, n'ont pas cet effet.
    
     Enfin, notez que toutes les requêtes du message Query auront la même valeur
     pour la fonction statement_timestamp(), car cet
     horodatage est mis à jour seulement lors de la réception d'un message
     Query. De ce fait, ils auront aussi tous la même valeur pour
     transaction_timestamp(), sauf dans les cas où la
     chaîne de requêtes finit avec une transaction précédemment démarrée et
     en commence une nouvelle.
    
Le protocole de requête étendue divise le protocole de requête simple décrit ci-dessus en plusieurs étapes. Le résultat des étapes préparatoires peut être ré-utilisé plusieurs fois pour améliorer l'efficacité. De plus, des fonctionnalités supplémentaires sont disponibles, tel que la possibilité de fournir des valeurs de données comme paramètres séparés au lieu d'avoir à les insérer directement dans la chaîne de la requête.
Dans le protocole étendu, le client envoie en premier lieu un message Parse, qui contient une chaîne de caractères pour la requête, avec en options quelques informations sur les types de données des paramètres, et le nom d'un objet représentant la requête préparée (une chaîne vide indiquera une requête préparée sans nom). La réponse est soit un message ParseComplete soit un message ErrorResponse. Les types de données des paramètres peuvent être des types de données indiquées par leur OID. Si aucun type n'est indiqué, l'analyseur tentera de deviner les types de données de la même façon qu'il le ferait pour des constantes de chaînes non typées.
     Un type de paramètre peut être laissé sans spécification en le configurant
     à zéro ou en faisant en sorte que le table d'OID des types de paramètres
     soit de taille inférieur au nombre de symboles de paramètres
     ($n) utilisés dans la chaîne
     de requête. Un autre cas spécial est qu'un type de paramètre peut être
     indiqué comme void (autrement dit, l'OID du pseudo-type
     void). Ceci permet l'utilisation de symboles de paramètre pour
     les paramètres de fonction qui sont en réalité des paramètres OUT.
     D'habitude, il n'y a pas de contexte dans lequel un paramètre
     void pourrait être utilisé, mais si un tel symbole de
     paramètre apparaît dans la liste de paramètres d'une fonction, il est en
     fait ignoré. Par exemple, un appel de fonction tel que
     foo($1,$2,$3,$4) pourrait correspondre à une fonction
     avec deux arguments IN et deux arguments OUT, si $3 et
     $4 sont indiqués comme étant de type void.
    
La chaîne de requête contenue dans un message Parse ne peut pas inclure plus d'une requête SQL ; dans le cas contraire une erreur SQL est levée. Cette restriction n'existe pas dans le protocole requête simple mais elle existe dans le protocole étendu parce que permettre à des requêtes préparées ou à des portails de contenir plusieurs commandes compliquerait indument le protocole.
    En cas de succès à la création, un objet nommé de requête préparé existe
    jusqu'à la fin de la session, sauf s'il est détruit explicitement. Une
    requête préparée sans nom dure seulement jusqu'à l'exécution du prochain
    message Parse pour une requête préparée sans nom. (Notez qu'un message Query
    détruit aussi une requête préparée sans nom.) Les requêtes préparées nommées
    doivent être explicitement fermées avant de pouvoir être redéfinies par un
    autre message Parse, mais ceci n'est pas requis pour une requête préparée
    sans nom. Les requêtes préparées nommées peuvent aussi être créées et
    accédées au niveau des commandes SQL en utilisant les instructions
    PREPARE et EXECUTE.
   
    Une fois qu'une requête préparée existe, elle peut être préparée pour une
    exécution en utilisant le message Bind. Ce dernier donne le nom de la
    requête préparée source (ou une chaîne vide dans le cas d'une requête
    préparée sans nom) et les valeurs à utiliser pour tous les paramètres
    présents dans la requête préparée. L'ensemble de paramètres fournis doit
    correspondre ceux requis par la requête préparée. (Si vous avez indiqué un
    ou plusieurs paramètres void dans le message Parse, donnez des
    valeurs NULL pour chacune dans le message Bind.) Bind spécifie aussi le
    format à utiliser pour toute donnée renvoyée par la requête ; le format
    peut être spécifié de façon globale ou par colonne. La réponse est soit
    BindComplete soit ErrorResponse.
   
     Le choix entre une sortie texte et une sortie binaire est déterminé par les
     codes format donnés dans Bind, quelque soit la commande SQL impliquée.
     L'attribut BINARY dans les déclarations de curseur est
     hors sujet lors de l'utilisation du protocole de requête étendue.
    
La planification/optimisation de la requête survient typiquement quand le message Bind est traité. Si la requête préparée n'a pas de paramètres ou si elle est exécutée de façon répétée, le serveur pourrait sauvegarde le plan créé et le ré-utiliser lors des messages Bind suivants pour la même requête préparée. Néanmoins, il le fera seulement s'il trouve qu'un plan générique peut être créé, sans être trop inefficace par rapport à un plan dépendant des valeurs spécifiques fournies pour les paramètres. Ceci survient de façon transparente pour ce qui concerne le protocole.
    S'il est créé avec succès, un objet portail nommé dure jusqu'à la fin de la
    transaction en cours, sauf en cas de destruction explicite. Un portail non
    nommé est détruit à la fin de la transaction ou dès l'exécution du prochain
    message Bind pour un portal non nommé. (Notez qu'un simple message Query
    détruit aussi le portail sans nom.) Les portails nommés doivent être fermés
    explicitement avant de pouvoir être redéfinis par un autre message Bind,
    mais ceci n'est pas requis pour un portail non nommé. Les portails nommés
    peuvent aussi être utilisés et accédés au niveau des commandes SQL, en
    utilisant les instructions DECLARE CURSOR et
    FETCH.
   
Une fois que le portail existe, il peut être exécuté en utilisant un message Execute. Ce dernier spécifie le nom du portail (une chaîne vide indique un portail non nommé) et un nombre maximum de lignes de résultat (zéro signifiant « récupère toutes les lignes »). Ce nombre a seulement un sens pour les portails contenant des commandes renvoyant des ensembles de lignes ; dans les autres cas, la commande est toujours exécutée jusqu'à sa fin, et le nombre de lignes est ignoré. Les réponses possibles à Exécute sont les mêmes que celles décrites ci-dessus pour les requêtes lancées via le protocole de requête simple, sauf que Execute ne cause pas l'exécution de ReadyForQuery ou RowDescription.
Si Execute termine avant la fin de l'exécution d'un portail (à cause de l'atteinte d'un nombre de lignes résultats différent de zéro), il enverra un message PortalSuspended ; l'apparence de ce message indique au client qu'un autre Execute devrait être exécuté contre le même portail pour terminer l'opération. Le message CommandComplete indiquant la fin de la commande SQL source n'est pas envoyé jusqu'à la fin de l'exécution du portail. De ce fait, une phase Execute est toujours terminée par l'apparition d'exactement un de ces messages : CommandComplete, EmptyQueryResponse (si le portail a été créé à partir d'une chaîne vide de requête), ErrorResponse ou PortalSuspended.
    À la fin de chaque série de messages du protocole de requête étendue, le
    client doit envoyer un message Sync. Ce message sans paramètre fait que le
    backend ferme la transaction en cours si elle n'est pas à l'intérieur d'un
    bloc de transaction BEGIN/COMMIT
    (« fermer » signifiant une validation s'il n'y a pas d'erreur et
    une annulation dans le cas d'une erreur). Une réponse ReadyForQuery est
    ensuite produite. Le but de Sync est de fournir un point de
    resynchronisation pour les erreurs. Quand une erreur est détectée lors du
    traitement de tout message du protocole de requête étendu, le backend envoie
    un message ErrorResponse, puis lit et annule les messages jusqu'à la
    réception d'un Sync, envoie un message ReadyForQuery et enfin retourne à un
    traitement habituelle des messages.  (Mais notez qu'une erreur dans le
    traitement du message Sync n'est pas ignoré  --  ceci assure qu'il y a
    bien un et un seul ReadyForQuery envoyé pour chaque Sync.)
   
     Sync ne ferme pas un bloc de transaction ouvert avec
     BEGIN.  Il est possible de détecter cette situation car
     le message ReadyForQuery inclut des informations de statut de la
     transaction.
    
En plus de ces opérations fondamentales et requises, il existe plusieurs opérations optionnelles pouvant être utilisées avec le protocole de requête étendue.
Le message Describe (variant du portail) indique le nom d'un portail existant (ou une chaîne vide pour le portail non nommé). La réponse est un message RowDescription décrivant les lignes qui seront retournées par l'exécution du portail ; ou un message NoData si le portail ne contient pas une requête qui renverra des lignes ; ou ErrorResponse s'il n'existe pas un tel portail.
Le message Describe (variant de la requête) indique le nom d'une requête préparée existante (ou une chaîne vide pour la requête préparée non nommée). La réponse est un message ParameterDescription décrivant les paramètres nécessaires pour la requête, suivi par un message RowDescription décrivant les lignes qui seront renvoyés quand la requête sera enfin exécutée (ou un message NoData si la requête ne renverra pas de lignes). Le message ErrorResponse est renvoyé si cette requête préparée n'existe pas. Notez que, comme Bind n'a pas été exécutée, les formats à utiliser pour les colonnes renvoyés ne sont pas encore connus du backend ; les champs de code format seront à zéro dans le message RowDescription dans ce cas.
Dans la plupart des scénarios, le client doit envoyer une variante ou l'autre de Describe avant d'envoyer le message Execute, pour s'assurer qu'il sait comment interpréter les résultats qu'il récupérera.
Le message Close ferme une requête préparée ou un portail existant, et libère les ressources. Ce n'est pas une erreur d'envoyer Close pour un nom inexistant de requête préparée ou de portail. La réponse est habituellement CloseComplete, mais pourrait être ErrorResponse si des difficultés sont rencontrées lors de la libération des ressources. Notez que fermer implicitement une requête préparée ferme tout portail ouvert qui était construit par cette requête.
Le message Flush ne cause pas la génération d'une sortie spécifique mais force le backend à renvoyer toutes les données en attente dans les buffers de sortie. Un Flush doit être envoyé après toute commande de requête étendue sauf Sync, si le client souhaite examiner les résultats de cette commande avant de lancer d'autres commandes. Sans Flush, les messages renvoyés par le backend seront combinés dans le plus petit nombre de paquets pour minimiser la surcharge réseau.
Le message Query en requête simple est approximativement équivalent à une série Parse, Bind, Describe portail, Execute, Close, Sync, en utilisant une requête préparée et un portail non nommés et aucun paramètre. Une différence est qu'il acceptera plusieurs requêtes SQL dans la chaîne de requête, réalisant automatiquement les séquences bind/describe/execute pour chaque requête, les unes à la suite des autres. Une autre différence est qu'il ne renvoie pas les messages ParseComplete, BindComplete, CloseComplete et NoData.
L'utilisation du protocole de requête étendue autorise les pipelines, autrement dit l'envoi d'une série de requêtes sans attendre que les premières se terminent. Ceci réduit le nombre d'aller/retour réseau nécessaire pour terminer une série d'opérations. Néanmoins, l'utilisateur doit faire attention au comportement souhaité si une des étapes échoue car les requêtes suivantes seront déjà envoyées au serveur.
    Une façon de gérer cela est de transformer la série complète de requête en
    une seule transaction, donc de l'entourer des commandes
    BEGIN ...  COMMIT. Cela n'aide
    cependant pas les personnes qui souhaiteraient que certaines commandes
    soient validées indépendamment des autres.
   
    Le protocole de requête étendue fournit un autre moyen pour gérer cette
    problématique. Il s'agit d'oublier d'envoyer les messages Sync entre les
    étapes qui sont dépendantes. Comme, après une erreur, le moteur ignorera les
    messages des commandes jusqu'à ce qu'il trouve un message Sync, cela
    autorise les commandes ultérieures d'un pipeline d'être automatiquement
    ignorées si une commande précédente échoue, sans que le client ait à gérer
    cela explicitement avec des commandes BEGIN et
    COMMIT. Les segments à valider indépendamment dans le
    pipeline peuvent être séparées par des messages Sync.
   
    Si le client n'a pas exécuté un BEGIN explicite, alors
    chaque Sync implique un COMMIT implicite si les étapes
    prédédentes ont réussi ou un ROLLBACK implicite si elles
    ont échoué. Néanmoins, il existe quelques commandes DDL (comme
    CREATE DATABASE) qui ne peuvent pas être exécutées dans
    un bloc de transaction. Si une de ces commandes est exécutée dans un
    pipeline, cela échouera sauf s'il s'agit de la première commande du pipeline.
    De plus, en cas de succès, cela forcera une validation immédiate pour
    préserver la cohérence de la base. De ce fait, un Sync suivant immédiatement une des ces
    commandes n'aura pas d'effet autre que de répondre avec ReadyForQuery.
   
Lors de l'utilisation de cette méthode, la fin du pipelin doit être déterminée en comptant les messages ReadyForQuery et en attendant que cela atteigne le nombre de Sync envoyés. Compter les réponses de fin de commande n'est pas fiable car certaines commandes pourraient être ignorées et donc ne pas produire de message de fin.
    Le sous-protocole d'appel de fonction permet au client de demander un appel
    direct de toute fonction qui existe dans le catalogue système
    pg_proc de la base de données. Le client doit avoir
    le droit d'exécution sur la fonction.
   
     Le sous-protocole d'appel de fonction est une ancienne fonctionnalité qu'il
     est certainement préférable d'éviter dans du nouveau code. Des résultats
     similaires peuvent être accomplis en configurant une requête préparée qui
     exécute SELECT function($1, ...). Le cycle de l'appel de
     fonction peut ensuite être remplacé avec les messages Bind/Execute.
    
Un cycle d'appel de fonction est initié par le client en envoyant un message FunctionCall au backend. Le backend envoie alors un ou plusieurs messages de réponse suivant le résultat de l'appel de fonction, et termine avec un message ReadyForQuery. Ce message informe le client qu'il peut envoyer une nouvelle requête ou un nouvel appel de fonction.
Les messages de réponse possible provenant du backend sont :
Une erreur est survenue
L'appel de fonction s'est terminé et a renvoyé le résultat donné dans le message. (Notez que le protocole d'appel de fonction peut seulement gérer un résultat scalaire simple, pas un type ligne ou un ensemble de résultats.)
Le traitement de l'appel de fonction est terminé. Le message ReadyForQuery sera toujours envoyé, que le traitement termine avec succès ou avec une erreur.
Un message d'avertissement a été lancé en relation avec l'appel de fonction. Les notes sont en plus des autres réponses, autrement dit le backend continuera à traiter la commande.
    La commande COPY permet une transfert de données en masse
    très rapide du ou à partir du serveur. Les opérations de copie vers le
    serveur (copy-in) ou à partir du serveur
    (copy-out) font basculer la connexion dans un
    sous-protocole distinct, qui dure jusqu'à la fin de l'opération.
   
    Le mode Copy-in (transfert de données vers le serveur)
    est initié quand le backend exécute une requête SQL COPY FROM
    STDIN. Le backend envoie un message CopyInResponse au client. Le
    client doit alors envoyer zéro ou plusieurs messages CopyData, formant un
    flux de données en entrée. (Les limites du message ne sont pas nécessaires
    liées aux limites des lignes, bien qu'il s'agit souvent d'un choix
    raisonnable.) Le client peut terminer le mode copy-in en
    envoyant soit un message CopyDone (permettant une fin avec succès) ou un
    message CopyFail (qui causera l'échec de la requête SQL
    COPY avec un message d'erreur). Le backend annule alors
    le mode de traitement de commande dans lequel il était entré au début de la
    commande COPY, qui sera soit le protocole de requête
    simple ou celui de requête étendu.  Il enverra ensuite soit un message
    CommandComplete (en cas de réussite) soit un message ErrorResponse (dans le
    cas contraire).
   
    Dans le cas d'une erreur détecté par le backend lors du mode
    copy-in (incluant la réception d'un message CopyFail), le
    backend enverra un message ErrorResponse. Si la commande
    COPY a été lancée via un message de requête étendue, le
    backend ignorera maintenant les messages du client jusqu'à la réception d'un
    message Sync. Après, il enverra un message ReadyForQuery et retournera à un
    traitement normal. Si la commande COPY a été lancé via un
    message Query, le reste de ce message est ignoré et le message ReadyForQuery
    est envoyé. Dans tous les cas, les messages CopyData, CopyDone ou CopyFail
    suivants envoyés par le client seront simplement ignorés.
   
    Le backend ignorera les messages Flush et Sync reçus lors du mode
    copy-in.  La réception de tout autre message qui ne
    concerne pas la copie constitue une erreur qui annulera l'état
    copy-in comme décrit ci-dessus. (L'exception pour Flush
    et Sync est pour simplifier les bibliothèques clientes qui envoient toujours
    Flush ou Sync après un message Execute, sans vérifier si la commande à
    exécuter est un COPY FROM STDIN.)
   
    Le mode Copy-out (transfert de données à
    partir du serveur) est initié lorsque le backend exécute une requête SQL
    COPY TO STDOUT. Le backend envoie un message
    CopyOutResponse au client, suivi par zéro ou plusieurs messages CopyData
    (toujours un par ligne), suivi par un message CopyDone. Le backend annulera
    alors le mode de traitement de commande dans lequel il était avant le
    lancement de COPY. Enfin, il envoie CommandComplete.  Le
    client ne peut pas annuler le transfert (sauf en fermant la connexion ou en
    envoyant une requête Cancel), mais il peut ignorer les messages CopyData et
    CopyDone indésirables.
   
    Dans le cas d'une erreur détectée par le backend en mode
    copy-out, le backend lancera un message ErrorResponse et
    reviendra en traitement normal.  Le client devrait traiter la réception de
    ErrorResponse comme terminant le mode copy-out.
   
    Il est possible que les messages NoticeResponse et ParameterStatus soient
    mélangés entre des messages CopyData ; les clients doivent gérer ces
    cas, et devraient être préparés aussi pour tout type de message asynchrone
    (voir Section 53.2.7). Sinon, tout type de message autre
    que CopyData ou CopyDone peut être traité comme terminant le mode
    copy-out.
   
    Il existe un autre mode relatif à la copie, appelé
    copy-both, qui permet des transferts de
    données en masse et très rapides vers et à partir du
    serveur. Le mode copy-both est initié quand un backend en
    mode walsender exécute une instruction START_REPLICATION.
    Le backend envoie un message CopyBothResponse au client. Le backend et le
    client peuvent ensuite envoyer des messages CopyData jusqu'à ce que l'un des
    deux envoie un message CopyDone. Une fois que le client a envoyé un message
    CopyDone, le connexion passe du mode copy-both au mode
    copy-out et le client ne peut plus envoyer de messages
    CopyData.  De la même façon, quand le serveur envoie un message CopyDone, la
    connexion passe en mode copy-in, et le serveur ne peut
    plus envoyer de messages CopyData. Une fois que les deux ont envoyé un
    message CopyDone, le mode de copie est terminé, et le backend revient au
    mode de traitement des commandes. Dans le cas où une erreur est détectée par
    le backend pendant le mode copy-both, le backend enverra
    un message ErrorResponse, ignorera les messages du client jusqu'à ce qu'un
    message Sync ne soit reçu, puis enverra un message ReadyForQuery avant de
    revenir au traitement normal.  Le client doit traiter la réception d'un
    message ErrorResponse comme terminant la copie dans les deux
    directions ; aucun message CopyDone ne devra être envoyé dans ce cas.
    Voir Section 53.4 pour plus d'informations sur le
    sous-protocole transmis sur le mode copy-both.
   
    Les messages CopyInResponse, CopyOutResponse et CopyBothResponse incluent
    des champs qui informent le client du nombre de colonnes par ligne et des
    codes format utilisés pour chaque colonne. (Sur l'implémentation actuelle,
    toutes les colonnes d'une opération COPY donnée
    utiliseront le même format, mais le design des messages ne le force pas.)
   
Il existe différents cas où le backend enverra des messages qui ne sont pas spécifiquement demandés par le flux de commande du client. Les clients doivent être préparés à gérer aussi ces messages à tout moment, même quand une requête n'est pas en cours. Au minimum, un client devrait vérifier ces cas avant de continuer à lire la réponse à une requête.
Il est possible que des messages NoticeResponse soient générés à cause d'une activité externe ; par exemple, si l'administrateur de la base de données ordonne un arrêt « rapide » de la base de données, le backend enverra un message NoticeResponse indiquant ce fait avant de fermer la connexion. Les clients doivent donc être prêts à accepter et afficher les messages NoticeResponse, même quand la connexion n'exécute pas de requêtes.
    Les messages ParameterStatus seront générés à chaque fois qu'une valeur
    change pour un des paramètres pour lesquels le backend pense que le client
    doit être notifié.  La plupart du temps, ceci survient en réponse à une
    commande SQL SET exécutée par le client, et ce cas est
    effectivement synchrone  --  mais il est aussi possible qu'un changement
    de valeur de paramètres survient parce que l'administrateur a modifié un
    fichier de configuration, puis envoyé le signal
    SIGHUP au serveur. De plus, si une commande
    SET est annulé, un message ParameterStatus approprié sera
    généré pour rapporter la valeur effective.
   
Il existe actuellement un ensemble, codé en dur, de paramètres pour lesquels un message ParameterStatus sera généré. En voici la liste :
| application_name | is_superuser | 
| client_encoding | scram_iterations | 
| DateStyle | server_encoding | 
| default_transaction_read_only | server_version | 
| in_hot_standby | session_authorization | 
| integer_datetimes | standard_conforming_strings | 
| IntervalStyle | TimeZone | 
    (default_transaction_read_only et
    in_hot_standby ne sont pas rapportés avant la version
    14 ; scram_iterations n'est par rapporté avant la
    version 16.)
    Notez que
    server_version,
    server_encoding et
    integer_datetimes
    sont des pseudos-paramètres qui ne peuvent pas changer après le démarrage.
    Cet ensemble pourrrait être modifié dans le futur, voire même devenir
    configurable. En conséquence, un client devrait simplement ignorer les
    messages ParameterStatus pour les paramètres qu'il ne comprend pas ou qui ne
    sont pas intéressants pour lui.
   
    Si un client exécute une commande LISTEN, alors le
    backend enverra un message NotificationResponse (à ne pas confondre avec
    NoticeResponse !) à chaque fois qu'une commande
    NOTIFY est exécutée pour le même nom de canal.
   
Actuellement, NotificationResponse peut seulement être envoyé en dehors d'une transaction, et donc il ne surviendra pas au milieu d'une série de réponses à des commandes, bien qu'il puisse survenir juste avant un message ReadyForQuery. Il est déconseillé de concevoir la logique du client comme assumant cela. Une bonne pratique est d'être capable d'accepter un message NotificationResponse à tout moment dans le protocole.
Lors du traitement d'une requête, le client pourrait demander l'annulation de la requête. La demande d'annulation n'est pas envoyée directement sur la connexion ouverte sur le backend pour des raisons d'efficacité de l'implémentation : nous ne voulons pas avoir le backend en train de vérifier constamment pour une nouvelle entrée en provenance du client lors du traitement de la requête. Les demandes d'annulation sont relativement peu fréquentes, donc nous pouvons les rendre un peu compliquées pour éviter un pénalité sur les cas normaux.
Pour demander une annulation, le client ouvre une nouvelle connexion au serveur et envoie un message CancelRequest, plutôt que le message StartupMessage qui serait habituellement envoyé lors d'une nouvelle connexion. Le serveur traitera cette demande, puis fermera la connexion. Pour des raisons de sécurité, aucune réponse directe n'est faite au message de demande d'annulation.
Un message CancelRequest sera ignoré sauf s'il contient la même donnée clé (PID et clé sécrète) passée au client lors de la connexion. Si la demande correspond au PID et à la clé secrète pour un backend en cours d'exécution d'une requête, le traitement de la requête est annulé. (Dans l'implémentation actuelle, ceci se fait en envoyant un signal spécial au processus backend qui traite la requête.)
Le signal d'annulation pourrait avoir un effet ou pas -- par exemple, s'il arrive après que le backend ait terminé le traitement de la requête, il n'aura aucun effet. Si l'annulation est réelle, la commande en cours est arrêtée avec un message d'erreur.
Le résultat de tout ceci est que, pour des raisons de sécurité et d'efficacité, le client n'a pas de façon de savoir si la requête d'annulation a réussi. Il doit continuer d'attendre que le backend réponse à la requête. Exécuter une annulation améliore simplement les chances que la requête en cours termine rapidement, et améliore les chances qu'elle échouera avec un message d'erreur au lieu d'un succès.
Comme la requête d'annulation est envoyée sur une nouvelle connexion au serveur et non pas via le lien standard de communication client/backend, il est possible d'envoyer une demande d'annulation pour tout processus, pas uniquement pour le client dont la requête est à annuler. Ceci apporte une flexibilité supplémentaire lors de la construction d'applications multi-processus. Cela introduit aussi un risque de sécurité dans le fait que des personnes non autorisées pourraient tenter d'annuler des requêtes. Le risque de sécurité est mitigé par le besoin d'une clé secrète générée dynamiquement, à fournir lors de demandes d'annulation.
La procédure normale et propre d'arrêt est que le client envoie un message Terminate et ferme immédiatement la connexion. Sur réception de ce message, le backend ferme la connexion et quitte.
Dans les rares cas (tel qu'un arrêt de base demandé par l'administrateur), le backend pourrait se déconnecter sans demande du client. Dans ce genre de cas, le backend tentera d'envoyer un message d'erreur ou d'information, donnant la raison de la déconnexion avant de fermer la connexion.
D'autres scénarios d'arrêt surgissent de différents cas d'échec, tel qu'un core dump d'un bout ou de l'autre, une perte du lien de communication, une perte de la synchronisation sur les messages, etc. Si soit le client soit le backend voit une fin inattendue de la connexion, il doit faire son ménage et quitter. Le client a l'option de lancer un nouveau backend en recontactant le serveur s'il ne veut pas quitter. Fermer la connexion est aussi conseillé si un type de message non reconnu est reçu car cela indique probablement la perte de synchronisation des messages.
    Pour un arrêt normal ou anormal, toute transaction ouverte est annulée, et
    non pas validée. Néanmoins, notez que si un client se déconnecter alors
    qu'une requête autre qu'un SELECT est en cours de
    traitement, le backend finira probablement la requête sans se rendre compte
    de la déconnexion. Si la requête est exécutée en dehors d'un bloc de
    transaction (séquence BEGIN ...
    COMMIT), alors ses résultats pourraient être validées
    avant que le backend ne s'aperçoive de la déconnexion.
   
Si PostgreSQL a été compilé avec le support de SSL, les communications client/backend peuvent être chiffrés en utilisant SSL. Cela fournit une sécurité sur la communication pour les environnements où des attaquants pourraient être en mesure de capturer le trafic de la session. Pour plus d'informations sur le chiffrement des sessions PostgreSQL avec SSL, voir Section 18.9.
    Pour initier une connexion chiffrée avec SSL, le client
    envoie dès le début un message SSLRequest au lieu de StartupMessage. Le
    serveur répond avec un seul octet contenant S ou
    N, indiquant s'il est, respectivement, prêt ou non à
    utiliser SSL. Le client pourrait fermer la connexion à ce
    point s'il n'est pas satisfait par la réponse. Pour continuer après un
    S, le client réalise une poignée de main
    SSL de démarrage (non décrit ici, car partie de la
    spécification SSL) avec le serveur. Si la poignée de main
    est réussie, le client continue avec l'habituel StartupMessage. Dans ce cas,
    le message StartupMessage et toutes les données qui suivent seront chiffrés
    avec SSL. Pour continuer après un N,
    le client envoie le message habituel StartupMessage et continue sans
    chiffrement.  (Il est aussi possible de lancer un message GSSENCRequest
    après une réponse N pour tenter l'utilisation du
    chiffrement GSSAPI à la place du chiffrement
    SSL.)
   
Le client doit aussi se préparer à gérer un message ErrorMessage en réponse à un message SSLRequest. Le client ne doit pas afficher ce message d'erreur à l'utilisateur/application car le serveur n'a pas été authentifié (CVE-2024-10977). Dans ce cas, la connexion doit être fermée mais le client pourrait choisir d'ouvrir une connexion propre et continuer sans demander SSL.
    Quand le chiffrement SSL peut être réalisé, le serveur
    est supposé envoyer l'octet S, puis attendre que le
    client initie une poignée de main SSL. Si des octets
    supplémentaires sont disponibles en lecture, cela signifie probablement
    qu'une attaque de type
    man-in-the-middle est en cours et tente de
    réaliser la technique buffer-stuffing (CVE-2021-23222).
    Les clients doivent être codés soit pour lire exactement un octet de la
    socket avant de renvoyer la socket à leur bibliothèque SSL ou de la traiter
    comme une violation du protocole s'ils voient qu'ils ont déjà des octets
    supplémentaires.
   
De la même façon, le serveur s'attend à ce que le client ne commence pas la négociation SSL tant qu'il n'a pas reçu la réponse en un octet du serveur à la demande de SSL. Si le client commence la négociation SSL immédiatement, sans attendre la réception de la réponse du serveur, cela peut réduire la latence de connexion d'un aller/retour. Néanmoins, cela a un coût : ne pas être capable de gérer le cas où le serveur envoie une réponse négative à la demande de SSL. Dans ce cas, au lieu de continuer avec une connexion GSSAPI ou non chiffrée ou une erreur de procotole, le serveur se déconnectera tout simplement.
Un message initial SSLRequest peut aussi être utilisé dans une connexion en cours d'ouverture pour envoyer un message CancelRequest.
Une autre façon d'initier le chiffrement SSL est disponible. Le serveur reconnaitra les connexions qui commencent immédiatement une négociation SSL sans paquet SSLRequest. Une fois la connexion SSL établie, le serveur attendra un paquet standard startup-request et continuera la négociation sur un canal chiffré. Dans ce cas, toute autre requête de chiffrement sera refusée. Cette méthode n'est pas préférée pour les outils généralistes car elle ne peut pas négotier le meilleur chiffrement de la connexion et ne peut pas gérer les connexions non chiffrées. Cependant, c'est utile pour des environnements où le serveur et le client sont contrôlés ensemble. Dans ce cas, cela évite une latence d'un aller/retour, et permet l'utilisation d'outils réseaux dépendants de connexions standards SSL. Lors de l'utilisation de connexions SSL de ce style, le client doit utiliser l'extension ALPN définie par la RFC 7301 pour se protéger contre les attaques de confusion de protocole. Le protocole PostgreSQL est enregistré sous le nom "postgresql" sur le resgistre IANA TLS ALPN Protocol IDs.
Alors que le protocole lui-même ne fournit pas de moyens pour que le serveur force un chiffrement SSL, l'administrateur peut configurer le serveur de telle façon qu'il rejette les sessions non chiffrées. Cela se fait pendant la vérification de l'authentification.
Si PostgreSQL a été compilé avec le support de GSSAPI, les communications client/backend peuvent être chiffrées en utilisant GSSAPI. Ceci fournit une sécurité de la communication dans les environnements où les attaquants pourraient être en mesure de capturer le trafic de la session. Pour plus d'informations sur le chiffrement des sessions PostgreSQL avec GSSAPI, voir Section 18.10.
    Pour initier une connexion chiffrée avec GSSAPI, le
    client doit au départ envoyer un message GSSENCRequest plutôt qu'un message
    StartupMessage. Le serveur répond avec un seul octet contenant
    G ou N, indiquant s'il est,
    respectivement, disposé ou non pour réaliser un chiffrement
    GSSAPI. Le client pourrait fermer la connexion à ce stage
    s'il n'est pas satisfait par la réponse. Pour continuer après un
    G, en utilisant les fonctions C de GSSAPI comme indiqué
    dans la RFC 2744 ou
    un équivalent, le client réalise une initialisation de
    GSSAPI en appelant
    gss_init_sec_context() dans une boucle et en envoyant
    le résultat au serveur, en commençant avec une entrée vide, et en continuant
    avec chaque résultat du serveur jusqu'à la fin. Lors de l'envoi de résultats
    de gss_init_sec_context() au serveur, il ajoute la
    longueur du message sous la forme d'un entier sous quatre octets dans
    l'ordre des octets du réseau.  Pour continuer après un N,
    il envoie le message habituel StartupMessage puis continue sans chiffrement.
    (Une autre solution est de lancer un message SSLRequest après une réponse
    N pour tenter l'utilisation d'un chiffrement
    SSL à la place du chiffrement GSSAPI.)
   
Le client doit aussi être préparé à gérer une réponse ErrorMessage pour GSSENCRequest provenant du serveur. Le client ne doit pas afficher ce message d'erreur à l'utilisation/application carle serveur n'a pas été authentifié (CVE-2024-10977). Dans ce cas, la connexion doit être termée, mais le client peut choisir d'ouvrir une nouvelle connexion et de continuer sans demander de chiffrement GSSAPI.
    Quand le chiffrement GSSAPI peut être réalisé, le serveur
    est supposé envoyer l'octet G, puis attendre que le
    client initie une poignée de main GSSAPI. Si des octets
    supplémentaires sont disponibles en lecture, cela signifie probablement
    qu'une attaque de type
    man-in-the-middle est en cours et tente de
    réaliser la technique buffer-stuffing (CVE-2021-23222).
    Les clients doivent être codés soit pour lire exactement un octet de la
    socket avant de renvoyer la socket à leur bibliothèque GSSAPI ou de la traiter
    comme une violation du protocole s'ils voient qu'ils ont déjà des octets
    supplémentaires à lire.
   
Un message initial GSSENCRequest peut aussi être utilisé dans une connexion en cours d'ouverture pour envoyer un message CancelRequest.
    Une fois que le chiffrement GSSAPI a été établi avec
    succès, le client utilise la fonction gss_wrap() pour
    chiffrer le message StartupMessage habituel et toutes les données qui
    suivent, ajoutant la longueur du résultat de gss_wrap()
    sous la forme d'un entier sous quatre octets dans l'ordre d'octets du réseau
    à la charge chiffrée réelle. Notez que le serveur acceptera seulement des
    paquets chiffrés provenant du client qui font moins de 16 Ko ;
    gss_wrap_size_limit() devrait être utilisé par le
    client pour déterminer la taille du message non chiffré qui sera contenu
    dans cette limite, et les messages plus larges devront être divisés en
    plusieurs appels à gss_wrap(). Les segments typiques
    sont 8 Ko de données non chiffrées, résultant en des paquets chiffrés
    légèrement supérieurs à 8 Ko mais bien contenu dans les 16 Ko
    maximum. Il est attendu que le serveur n'envoie pas de paquets de plus de
    16 ;Ko au client.
   
Alors que le protocole lui-même ne fournit pas de moyens pour que le serveur force un chiffrement GSSAPI, l'administrateur peut configurer le serveur de telle façon qu'il rejette les sessions non chiffrées. Cela se fait pendant la vérification de l'authentification.