Windows Sockets: przykład gniazd korzystających z archiwów

W tym artykule przedstawiono przykład użycia klasy CSocket. Przykład wykorzystuje CArchive obiekty do serializacji danych za pośrednictwem gniazda. Należy pamiętać, że nie jest to serializacja dokumentu do lub z pliku.

W poniższym przykładzie pokazano, jak używać archiwum do wysyłania i odbierania danych za pośrednictwem CSocket obiektów. Przykład został zaprojektowany tak, aby dwa wystąpienia aplikacji (na tej samej maszynie lub na różnych maszynach w sieci) wymieniały dane. Jedno wystąpienie wysyła dane, które drugie wystąpienie odbiera i potwierdza. Każda aplikacja może zainicjować wymianę i może działać jako serwer lub jako klient z inną aplikacją. Następująca funkcja jest zdefiniowana w klasie widoków aplikacji:

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

Najważniejszą rzeczą w tym przykładzie jest to, że jego struktura jest równoległa względem funkcji MFC Serialize . Funkcja PacketSerialize składowa składa się z instrukcji if z klauzulą else . Funkcja odbiera dwa odwołania CArchive jako parametry: arData i arAck. Jeśli obiekt archiwum arData jest ustawiony na przechowywanie (wysyłanie), if gałąź jest wykonywana; w przeciwnym razie jeśli arData jest ustawiona na ładowanie (odbieranie), funkcja przyjmuje else gałąź. Aby uzyskać więcej informacji na temat serializacji w MFC, zobacz Serializacja.

Uwaga

Zakłada się, że obiekt arAck archive jest przeciwieństwem arData. Jeśli arData jest do wysyłania, arAck odbiera, a odwrotnie ma wartość true.

W przypadku wysyłania przykładowa funkcja wykonuje pętle dla określonej liczby razy, za każdym razem generując dane losowe do celów demonstracyjnych. Aplikacja uzyska rzeczywiste dane z jakiegoś źródła, takiego jak plik. Operator wstawiania archiwum arData (<<) służy do wysyłania strumienia trzech kolejnych fragmentów danych:

  • "nagłówek", który określa charakter danych (w tym przypadku wartość zmiennej bValue i liczbę kopii, które zostaną wysłane).

    Oba elementy są generowane losowo w tym przykładzie.

  • Określona liczba kopii danych.

    Pętla wewnętrzna for wysyła wartość bValue określoną liczbę razy.

  • Ciąg o nazwie strText wyświetlany użytkownikowi przez odbiorcę.

W przypadku odbierania funkcja działa podobnie, z tą różnicą, że używa operatora wyodrębniania archiwum (>>), aby pobrać dane z archiwum. Aplikacja odbierającą weryfikuje odbierane dane, wyświetla końcowy komunikat "Odebrano", a następnie wysyła z powrotem komunikat "Wysłane" dla aplikacji wysyłającej do wyświetlenia.

W tym modelu komunikacji słowo "Odebrano", komunikat wysłany w zmiennej strText , jest wyświetlany na drugim końcu komunikacji, dlatego określa użytkownikowi odbierającemu, że odebrano pewną liczbę pakietów danych. Odbiorca odpowiada za pomocą podobnego ciągu z napisem "Sent", aby wyświetlić go na ekranie oryginalnego nadawcy. Potwierdzenie obu ciągów wskazuje, że nastąpiła pomyślna komunikacja.

Uwaga

Jeśli piszesz program kliencki MFC do komunikowania się z ustalonymi serwerami (innych niż MFC), nie wysyłaj obiektów języka C++ za pośrednictwem archiwum. Jeśli serwer nie jest aplikacją MFC, która rozumie rodzaje obiektów, które chcesz wysłać, nie będzie mogła odbierać i deserializować obiektów. Przykład w artykule Windows Sockets: Byte Ordering pokazuje komunikację tego typu.

Aby uzyskać więcej informacji, zobacz Windows Sockets Specification: htonl, htons, ntohl, ntohs. Aby uzyskać więcej informacji, zobacz:

Zobacz też

Gniazda systemu Windows w MFC
CArchive::IsStoring
CArchive::, operator <<
CArchive::, operator >>
CArchive::Flush
CObject::Serialize