次の方法で共有


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

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

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

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 メンバー関数は、else 句を含む if ステートメントで構成されています。 この関数は、arDataarAck の 2 つの CArchive 参照をパラメーターとして受け取ります。 arData アーカイブ オブジェクトが保存 (送信) 用に設定されている場合は、if 分岐が実行されます。arData が読み込み (受信) 用に設定されている場合、関数は else 分岐を実行します。 MFC でのシリアル化の詳細については、シリアル化に関する記事を参照してください。

Note

arAck アーカイブ オブジェクトは、arData の反対と見なされます。 arData が送信用の場合、arAck が受信します。その逆も同様です。

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

  • データの性質を指定する "ヘッダー" (ここでは、bValue 変数の値と送信されるコピーの数)。

    この例では、どちらの項目もランダムに生成されます。

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

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

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

受信の場合、この関数はアーカイブの抽出演算子 (>>) を使用してアーカイブからデータを取得する点を除き、同様に動作します。 受信側のアプリケーションは、受信したデータを確認し、最後の "Received" メッセージを表示した後、送信側のアプリケーションが表示する "Sent" というメッセージを返送します。

この通信モデルでは、strText 変数で送信されるメッセージである "Received" という単語は、通信の相手側に表示されます。そのため、受信側のユーザーに対して、特定の数のデータ パケットを受信したことが示されます。 受信者は、元の送信者の画面に表示するための "Sent" という同様の文字列で応答します。 両方の文字列を受信すると、通信が成功したことになります。

注意事項

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

詳細については、Windows ソケット仕様の htonlhtonsntohlntohs を参照してください。 詳細については、以下も参照してください。

関連項目

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