Windows Sockets: Beispiel für Sockets mithilfe der Archive

In diesem Artikel wird ein Beispiel für die Verwendung von Klassen-CSocket dargestellt. Im Beispiel werden CArchive Objekte verwendet, um Daten über einen Socket zu serialisieren. Beachten Sie, dass dies keine Dokument serialisierung in oder aus einer Datei ist.

Im folgenden Beispiel wird veranschaulicht, wie Sie das Archiv zum Senden und Empfangen von Daten über CSocket Objekte verwenden. Das Beispiel ist so konzipiert, dass zwei Instanzen der Anwendung (auf demselben Computer oder auf verschiedenen Computern im Netzwerk) Daten austauschen. Eine Instanz sendet Daten, die die andere Instanz empfängt und bestätigt. Entweder kann eine Anwendung einen Austausch initiieren und entweder als Server oder als Client für die andere Anwendung fungieren. Die folgende Funktion wird in der Ansichtsklasse der Anwendung definiert:

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();
      }
   }
}

Das Wichtigste an diesem Beispiel ist, dass die Struktur parallel zu einer MFC-Funktion Serialize ist. Die PacketSerialize Memberfunktion besteht aus einer if Anweisung mit einer else Klausel. Die Funktion empfängt zwei CArchive-Verweise als Parameter: arData und arAck. Wenn das arData-Archivobjekt zum Speichern (Senden) festgelegt ist, wird die if Verzweigung ausgeführt. Andernfalls wird arData zum Laden (Empfangen) festgelegt, übernimmt die Funktion die else Verzweigung. Weitere Informationen zur Serialisierung in MFC finden Sie unter Serialisierung.

Hinweis

Das arAck-Archivobjekt wird angenommen, dass es sich um das Gegenteil von arData handelt. Wenn arData zum Senden dient, empfängt arAck und umgekehrt.

Beim Senden wird die Beispielfunktion für eine bestimmte Anzahl von Wiederholungen ausgeführt, wobei jedes Mal zufällige Daten zu Demonstrationszwecken generiert werden. Ihre Anwendung würde echte Daten aus einer Quelle abrufen, z. B. eine Datei. Der Einfügeoperator des arData-Archivs (<<) wird verwendet, um einen Datenstrom mit drei aufeinander folgenden Datenblöcken zu senden:

  • Ein "Header", der die Art der Daten angibt (in diesem Fall der Wert der bValue-Variablen und wie viele Kopien gesendet werden).

    Beide Elemente werden zufällig für dieses Beispiel generiert.

  • Die angegebene Anzahl der Kopien der Daten.

    Die innere for Schleife sendet bValue die angegebene Anzahl von Malen.

  • Eine Zeichenfolge namens strText , die der Empfänger für den Benutzer anzeigt.

Für den Empfang funktioniert die Funktion ähnlich, mit der Ausnahme, dass sie den Extraktionsoperator (>>) des Archivs zum Abrufen von Daten aus dem Archiv verwendet. Die empfangende Anwendung überprüft die empfangenen Daten, zeigt die endgültige "Empfangene" Nachricht an und sendet dann eine Nachricht zurück, die "Gesendet" besagt, damit die sendende Anwendung angezeigt wird.

In diesem Kommunikationsmodell wird das Wort "Empfangen", die in der strText-Variable gesendete Nachricht, am anderen Ende der Kommunikation angezeigt, sodass der empfangende Benutzer angibt, dass eine bestimmte Anzahl von Datenpaketen empfangen wurde. Der Empfänger antwortet mit einer ähnlichen Zeichenfolge, die "Gesendet" lautet, für die Anzeige auf dem Bildschirm des ursprünglichen Absenders. Der Empfang beider Zeichenfolgen gibt an, dass eine erfolgreiche Kommunikation aufgetreten ist.

Achtung

Wenn Sie ein MFC-Clientprogramm für die Kommunikation mit etablierten (nicht MFC)-Servern schreiben, senden Sie keine C++-Objekte über das Archiv. Es sei denn, der Server ist eine MFC-Anwendung, die die Art der zu sendenden Objekte versteht, kann sie Ihre Objekte nicht empfangen und deserialisieren. Ein Beispiel im Artikel Windows Sockets: Byte-Sortierung zeigt eine Kommunikation dieses Typs.

Weitere Informationen finden Sie unter Windows Sockets Specification: htonl, htons, ntohl, ntohs. Weitere Informationen finden Sie auch unter:

Siehe auch

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