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

更新 : 2007 年 11 月

ここでは、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 文が使われています。この関数は、パラメータとして CArchive の 2 つの参照 arData と arAck を使用します。arData アーカイブ オブジェクトを格納 (送信) 用に設定すると、if 分岐が実行されます。arData を読み込み (受信) 用に設定すると、関数は else 分岐を選択します。MFC におけるシリアル化の詳細については、「要素のシリアル化」を参照してください。

dya2hz72.alert_note(ja-jp,VS.90).gifメモ :

arAck アーカイブ オブジェクトは、arData に対応するオブジェクトと見なされます。arData が送信すると arAck が受信し、arAck が送信すると arData が受信します。

送出側のサンプル関数は、指定された回数のループ処理を実行し、そのたびにデモ用のランダム データを生成します。アプリケーションでは、ファイルなどのソースから実際のデータを取得します。arData アーカイブの出力ストリーム演算子 (<<) で送信されるストリームは、次の 3 つのデータから構成されます。

  • データの性質を示す "ヘッダー" (この場合は、変数 Value の値とコピーの送信回数)

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

  • データのコピー回数の指定

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

  • 受信側がユーザーに対して侮ヲする文字列 strText

受信側の関数の動作もほとんど同じです。ただし、アーカイブの入力ストリーム演算子 (>>) を使って、アーカイブからデータを取得します。受信側アプリケーションは、受信したデータを検査し、最後の "Received" メッセージを表示してから、"Sent" メッセージを送出側アプリケーションに送り返して表示させます。

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

dya2hz72.alert_caution(ja-jp,VS.90).gif注意 :

確立済みの非 MFC サーバーと通信する MFC クライアント プログラムを記述する場合は、C++ オブジェクトをアーカイブ経由で送らないようにしてください。サーバーは、送出するオブジェクトの種類を認識できる MFC アプリケーションでない限り、このオブジェクトを受信することも逆シリアル化することもできません。「Windows ソケット : バイトの順序付け」にこの種の通信例があります。

詳細については、Windows ソケットの仕様で htonlhtonsntohlntohs を参照してください。また、詳細については、次のトピックも参照してください。

参照

概念

MFC における Windows ソケット

参照

CArchive::IsStoring

CArchive::operator <<

CArchive::operator >>

CArchive::Flush

CObject::Serialize