次の方法で共有


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

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

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

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

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

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

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

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

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

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

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

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

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

注意事項

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

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

こちらも参照ください

MFC の Windows ソケット
CArchive::IsStoring
CArchive::operator <<
CArchive::operator >>
CArchive::Flush
CObject::Serialize