Windows Sockets : exemple de sockets utilisant des archives

Cet article présente un exemple d’utilisation de la classe CSocket. L’exemple utilise des objets pour sérialiser des CArchive données via un socket. Notez qu’il ne s’agit pas d’une sérialisation de documents vers ou à partir d’un fichier.

L’exemple suivant montre comment utiliser l’archive pour envoyer et recevoir des données via CSocket des objets. L’exemple est conçu afin que deux instances de l’application (sur la même machine ou sur des ordinateurs différents sur le réseau) échangent des données. Une instance envoie des données, que l’autre instance reçoit et reconnaît. L’une ou l’autre application peut lancer un échange et agir en tant que serveur ou client à l’autre application. La fonction suivante est définie dans la classe d’affichage de l’application :

void PacketSerialize(long nPackets, CArchive &arData, CArchive &arAck)
{
   BYTE bValue = 0;
   WORD nCopies = 0;

   if (arData.IsStoring())
   {
      CString strText;
      errno_t err;
      unsigned int number;

      for (int p = 0; p < nPackets; p++)
      {
         err = rand_s(&number);
         // if (err == 0)...
         bValue = (BYTE)(number % 256);

         err = rand_s(&number);
         // if (err == 0)...
         nCopies = (WORD)(number % 32000);

         // Send header information
         arData << bValue << nCopies;
         for (int c = 0; c < nCopies; c++)
         {
            // Send data
            arData << bValue;
         }

         strText.Format(_T("Sender sent packet %d of %d (Value = %d, Copies = %d)"),
                        p + 1, nPackets, (int)bValue, nCopies);

         // Send receipt string
         arData << strText;
         arData.Flush();

         // Receive acknowledgment
         arAck >> strText;
         // display it
         DisplayMessage(strText);
      }
   }
   else
   {
      CString strText;
      BYTE bCheck;

      for (int p = 0; p < nPackets; p++)
      {
         // Receive header information
         arData >> bCheck >> nCopies;
         for (int c = 0; c < nCopies; c++)
         {
            // Receive data
            arData >> bValue;
            if (bCheck != bValue)
            {
               AfxMessageBox(_T("Packet Failure"));
            }
         }

         // Receive receipt string and display it
         arData >> strText;
         DisplayMessage(strText);

         strText.Format(_T("Recipient received packet %d of %d (Value = %d, Copies = %d)"),
                        p + 1, nPackets, (int)bValue, nCopies);

         // Send acknowledgment
         arAck << strText;
         arAck.Flush();
      }
   }
}

La chose la plus importante à propos de cet exemple est que sa structure est parallèle à celle d’une fonction MFC Serialize . La PacketSerialize fonction membre se compose d’une if instruction avec une else clause. La fonction reçoit deux références CArchive en tant que paramètres : arData et arAck. Si l’objet d’archive arData est défini pour le stockage (envoi), la if branche s’exécute ; sinon, si arData est défini pour le chargement (réception) la fonction prend la else branche. Pour plus d’informations sur la sérialisation dans MFC, consultez Sérialisation.

Remarque

L’objet d’archive arAck est supposé être l’opposé d’arData. Si arData est destiné à l’envoi, arAck reçoit et l’inverse est vrai.

Pour l’envoi, l’exemple de boucle de fonction pour un nombre spécifié de fois, chaque fois que vous générez des données aléatoires à des fins de démonstration. Votre application obtiendrait des données réelles à partir de certaines sources, telles qu’un fichier. L’opérateur d’insertion de l’archive arData (<<) est utilisé pour envoyer un flux de trois blocs consécutifs de données :

  • Un « en-tête » qui spécifie la nature des données (dans ce cas, la valeur de la variable bValue et le nombre de copies qui seront envoyées).

    Les deux éléments sont générés de façon aléatoire pour cet exemple.

  • Nombre spécifié de copies des données.

    La boucle interne for envoie bValue le nombre de fois spécifié.

  • Chaîne appelée strText que le récepteur affiche à son utilisateur.

Pour recevoir, la fonction fonctionne de la même façon, sauf qu’elle utilise l’opérateur d’extraction de l’archive (>>) pour obtenir des données à partir de l’archive. L’application de réception vérifie les données qu’elle reçoit, affiche le dernier message « Reçu », puis renvoie un message indiquant « Envoyé » pour que l’application d’envoi s’affiche.

Dans ce modèle de communication, le mot « Reçu », le message envoyé dans la variable strText , est destiné à être affiché à l’autre extrémité de la communication, de sorte qu’il spécifie à l’utilisateur destinataire qu’un certain nombre de paquets de données ont été reçus. Le récepteur répond avec une chaîne similaire qui indique « Envoyé », pour l’affichage sur l’écran de l’expéditeur d’origine. La réception des deux chaînes indique que la communication réussie s’est produite.

Attention

Si vous écrivez un programme client MFC pour communiquer avec des serveurs (non-MFC) établis, n'envoyez pas les objets C++ à l'archive. Sauf si le serveur est une application MFC qui comprend les types d’objets que vous souhaitez envoyer, il ne pourra pas recevoir et désérialiser vos objets. Un exemple de l’article Windows Sockets : Ordre d’octets affiche une communication de ce type.

Pour plus d’informations, consultez Spécification windows Sockets : htonl, htons, ntohl, ntohs. Pour plus d’informations, consultez :

Voir aussi

Windows Sockets dans MFC
CArchive ::IsStoring
CArchive ::operator <<
CArchive ::operator >>
CArchive ::Flush
CObject ::Serialize