次の方法で共有


Windows ソケット: アーカイブと連携するソケットのしくみ

この記事では、 CSocket オブジェクト、 CSocketFile オブジェクト、および CArchive オブジェクトを組み合わせて、Windows ソケットを介したデータの送受信を簡略化する方法について説明します。

Windows ソケット: アーカイブを使用するソケットの例に関する記事では、PacketSerialize関数について説明します。 PacketSerialize例のアーカイブ オブジェクトは、MFC Serialize 関数に渡されるアーカイブ オブジェクトとよく似ています。 基本的な違いは、ソケットの場合、アーカイブは標準 の CFile オブジェクト (通常はディスク ファイルに関連付けられている) ではなく、 CSocketFile オブジェクトにアタッチされる点です。 CSocketFile オブジェクトは、ディスク ファイルに接続するのではなく、CSocket オブジェクトに接続します。

CArchive オブジェクトはバッファーを管理します。 格納 (送信) アーカイブのバッファーがいっぱいになると、関連付けられている CFile オブジェクトによってバッファーの内容が書き出されます。 ソケットに接続されているアーカイブのバッファーをフラッシュすることは、メッセージの送信と同じです。 読み込み (受信) アーカイブのバッファーがいっぱいになると、 CFile オブジェクトはバッファーが再び使用可能になるまで読み取りを停止します。

クラス CSocketFileCFileから派生しますが、配置関数 (SeekGetLengthなど)、ロック関数 (SetLengthLockRange)、UnlockRange関数などの GetPosition メンバー関数はサポートされていません。 CSocketFile オブジェクトは、関連付けられている CSocket オブジェクトとの間でバイトシーケンスを書き込むか読み取る必要があります。 ファイルは関係しないため、 SeekGetPosition などの操作は意味をなしません。 CSocketFileCFileから派生しているため、通常、これらのメンバー関数はすべて継承されます。 これを防ぐために、サポートされていないCFileメンバー関数は、CSocketFile をスローするためにでオーバーライドされます。

CSocketFile オブジェクトは、CSocket オブジェクトのメンバー関数を呼び出して、データを送受信します。

次の図は、通信の両側にあるこれらのオブジェクト間の関係を示しています。

CArchive、CSocketFile、および CSocket。
CArchive、CSocketFile、および CSocket

この明らかな複雑さの目的は、ソケットの詳細を自分で管理する必要からあなたを保護することです。 ソケット、ファイル、アーカイブを作成し、アーカイブに挿入するかアーカイブからデータを抽出して、データの送受信を開始します。 CArchiveCSocketFileおよび CSocket は、バックグラウンドで詳細を管理します。

CSocket オブジェクトは、実際には 2 状態オブジェクトです。非同期 (通常の状態) と同期する場合があります。 非同期状態では、ソケットはフレームワークから非同期通知を受信できます。 ただし、データの受信や送信などの操作中に、ソケットは同期になります。 つまり、同期操作が完了するまで、ソケットはそれ以上の非同期通知を受け取らなくなります。 モードが切り替わるため、たとえば、次のような操作を行うことができます。

void CMySocket::OnReceive(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      CSocketFile file(this);
      CArchive ar(&file, CArchive::load);
      CString str;

      ar >> str;
   }
}

CSocketが 2 状態オブジェクトとして実装されていない場合は、前の通知の処理中に、同じ種類のイベントに対して追加の通知を受信できる可能性があります。 たとえば、OnReceiveの処理中にOnReceive通知を受け取る場合があります。 上記のコード フラグメントでは、アーカイブから str を抽出すると再帰が発生する可能性があります。 状態を切り替えることで、 CSocket は追加の通知を防ぐことで再帰を防ぎます。 一般的なルールは、通知内の通知はありません。

CSocketFileは、CArchive オブジェクトなしで (制限付き) ファイルとして使用することもできます。 既定では、 CSocketFile コンストラクターの bArchiveCompatible パラメーターは TRUE です。 これは、ファイル オブジェクトがアーカイブで使用されることを指定します。 アーカイブなしでファイル オブジェクトを使用するには、bArchiveCompatible パラメーターに FALSE を渡します。

"アーカイブ互換" モードでは、 CSocketFile オブジェクトのパフォーマンスが向上し、"デッドロック" の危険性が軽減されます。送信側と受信側の両方のソケットが互いに待機しているか、共通リソースを待機しているときにデッドロックが発生します。 この状況は、CArchive オブジェクトがCSocketFile オブジェクトと同様にCFileを操作した場合に発生する可能性があります。 CFileでは、アーカイブは、受信したバイト数が要求よりも少ない場合、ファイルの末尾に達したと想定できます。 ただし、 CSocketFileでは、データはメッセージ ベースです。バッファーには複数のメッセージを含めることができるため、要求されたバイト数より少ない数を受信しても、ファイルの終わりを意味しません。 この場合、アプリケーションは CFileと同様にブロックせず、バッファーが空になるまでバッファーからのメッセージの読み取りを続行できます。 CArchive 関数は、このような場合にアーカイブのバッファーの状態を監視するのに役立ちます。

詳細については、「Windows ソケット: アーカイブでのソケットの使用」を参照してください。

こちらも参照ください

MFC の Windows ソケット
CObject::Serialize