Windows ソケット: アーカイブを使用するソケットの例

この記事では、クラス CSocketの使用例を示します。 この例では、 CArchive オブジェクトを使用してソケットを介してデータをシリアル化します。 これは、ファイルとの間でドキュメントをシリアル化するものではないことに注意してください。

次の例は、アーカイブを使用してオブジェクトを介してデータを送受信する方法を示してい CSocket ます。 この例は、アプリケーションの2つのインスタンス (同じコンピューター上またはネットワーク上の別のコンピューター上) がデータを交換するように設計されています。 一方のインスタンスはデータを送信し、もう一方のインスタンスはデータを受信して確認します。 どちらのアプリケーションも exchange を開始でき、サーバーとして、または他のアプリケーションに対するクライアントとして機能できます。 アプリケーションの view クラスでは、次の関数が定義されています。

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 れます。 関数は、 Ardata および ardata という2つの CArchive参照をパラメーターとして受け取ります。 Ardata アーカイブオブジェクトが格納 (送信) 用に設定されている場合は、分岐が実行されます if 。それ以外の場合は、 ardata が読み込み (受信) 用に設定されていると、関数は分岐を受け取り else ます。 MFC でのシリアル化の詳細については、「 シリアル化」を参照してください。

注意

Arack archive オブジェクトは、 arack の逆であると見なされます。 Ardata が送信用であり、 ardata が受信され、逆の場合は true になります。

送信の場合、例の関数は、デモンストレーションのためにランダムなデータを生成するたびに、指定された回数だけループします。 アプリケーションでは、ファイルなどのソースから実際のデータを取得します。 Ardata archive の挿入演算子 ( << ) は、次の3つの連続したデータチャンクのストリームを送信するために使用されます。

  • データの性質を指定する "ヘッダー"。この場合は、 Bvalue 変数の値と送信するコピーの数を指定します。

    この例では、両方の項目がランダムに生成されます。

  • 指定されたデータのコピー数。

    内側 for のループは、指定された回数だけ bvalue を送信します。

  • 受信者がユーザーに表示する strText という文字列。

受信の場合、関数は同様に動作しますが、アーカイブの抽出演算子 ( >> ) を使用してアーカイブからデータを取得する点が異なります。 受信側のアプリケーションは、受信したデータを検証し、最終的な "受信済み" メッセージを表示して、送信元アプリケーションが表示する "送信" というメッセージを返信します。

この通信モデルでは、 strText 変数で送信されたメッセージである "received" という語が通信のもう一方の端に表示されます。そのため、受信側のユーザーに対して、特定の数のデータパケットを受信したことを指定します。 受信者は、元の送信者の画面に表示するために、"送信済み" という類似した文字列を返します。 両方の文字列を受け取ると、通信が成功したことを示します。

注意事項

確立された (非 MFC) サーバーと通信するように MFC クライアントプログラムを作成している場合は、アーカイブを通じて C++ オブジェクトを送信しないでください。 サーバーが、送信するオブジェクトの種類を認識する MFC アプリケーションでない限り、オブジェクトを受信したり、逆シリアル化したりすることはできません。 「 Windows ソケット: バイトの順序 」の例では、この型の通信が示されています。

詳細については、「Windows Sockets Specification: htonlhtonsntohlntohs」を参照してください。 また、詳細については、以下を参照してください。

関連項目

MFC における Windows ソケット
CArchive:: IsStoring
CArchive:: operator <<
CArchive:: operator >>
CArchive:: Flush
CObject:: Serialize