Поделиться через


Сокеты Windows. Пример сокетов с использованием архивов

В этой статье представлен пример использования класса CSocket. В примере используются CArchive объекты для сериализации данных через сокет. Обратите внимание, что это не сериализация документов в файл или из файла.

В следующем примере показано, как использовать архив для отправки и получения данных через CSocket объекты. Этот пример разработан таким образом, чтобы два экземпляра приложения (на одном компьютере или на разных компьютерах в сети) обменились данными. Один экземпляр отправляет данные, которые другой экземпляр получает и подтверждает. Любое приложение может инициировать обмен, и либо может выступать в качестве сервера, либо в качестве клиента для другого приложения. Следующая функция определена в классе представления приложения:

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

Самое важное в этом примере заключается в том, что его структура параллелит ее структуру функции MFC Serialize . Функция-член PacketSerialize состоит из инструкции if с предложением else . Функция получает две ссылки CArchive в качестве параметров: arData и arAck. Если для хранения (отправки) задан объект архива arData, if ветвь выполняется; в противном случае, если arData задано для загрузки (получения), функция принимает else ветвь. Дополнительные сведения о сериализации в MFC см. в разделе "Сериализация".

Примечание.

Предполагается, что объект архива arAck является противоположностью arData. Если arData предназначено для отправки, arAck получает, и наоборот имеет значение true.

Для отправки примеры циклов функций для указанного количества раз каждый раз, при создании некоторых случайных данных для демонстрационных целей. Приложение получит реальные данные из какого-то источника, например файла. Оператор вставки архива arData используется<< для отправки потока из трех последовательных блоков данных:

  • Заголовок, указывающий характер данных (в этом случае значение переменной bValue и количество копий будет отправлено).

    Оба элемента создаются случайным образом для этого примера.

  • Указанное количество копий данных.

    Внутренний for цикл отправляет bValue указанное количество раз.

  • Строка с именем strText , отображаемая получателем для своего пользователя.

Для получения функция работает аналогично, за исключением того, что он использует оператор извлечения архива (>>) для получения данных из архива. Принимающее приложение проверяет полученные данные, отображает окончательное сообщение "Получено", а затем отправляет обратно сообщение, которое говорит "Отправлено" для отображения приложения отправки.

В этой модели связи слово "Получено", отправленное в переменной strText , отображается в другом конце связи, поэтому он указывает получателю, что определенное количество пакетов данных было получено. Получатель отвечает с аналогичной строкой, которая говорит "Sent", для отображения на экране исходного отправителя. Получение обеих строк указывает на то, что произошло успешное взаимодействие.

Внимание

Если вы пишете клиентную программу MFC для взаимодействия с установленными (не MFC) серверами, не отправляйте объекты C++ через архив. Если сервер не является приложением MFC, которое понимает типы объектов, которые вы хотите отправить, он не сможет получать и десериализировать объекты. Пример в статье Сокеты Windows: Порядок байтов показывает связь с этим типом.

Дополнительные сведения см. в спецификации сокетов Windows: htonl, htons, ntohl, ntohs. Кроме того, дополнительные сведения см. в следующей статье:

См. также

Сокеты Windows в MFC
CArchive::IsStoring
CArchive::operator <<
CArchive::operator >>
CArchive::Flush
CObject::Serialize