この記事では、 CSocket オブジェクト、 CSocketFile オブジェクト、および CArchive オブジェクトを組み合わせて、Windows ソケットを介したデータの送受信を簡略化する方法について説明します。
Windows ソケット: アーカイブを使用するソケットの例に関する記事では、PacketSerialize
関数について説明します。 PacketSerialize
例のアーカイブ オブジェクトは、MFC Serialize 関数に渡されるアーカイブ オブジェクトとよく似ています。 基本的な違いは、ソケットの場合、アーカイブは標準 の CFile オブジェクト (通常はディスク ファイルに関連付けられている) ではなく、 CSocketFile
オブジェクトにアタッチされる点です。 CSocketFile
オブジェクトは、ディスク ファイルに接続するのではなく、CSocket
オブジェクトに接続します。
CArchive
オブジェクトはバッファーを管理します。 格納 (送信) アーカイブのバッファーがいっぱいになると、関連付けられている CFile
オブジェクトによってバッファーの内容が書き出されます。 ソケットに接続されているアーカイブのバッファーをフラッシュすることは、メッセージの送信と同じです。 読み込み (受信) アーカイブのバッファーがいっぱいになると、 CFile
オブジェクトはバッファーが再び使用可能になるまで読み取りを停止します。
クラス CSocketFile
はCFile
から派生しますが、配置関数 (、Seek
、GetLength
など)、ロック関数 (SetLength
、LockRange
)、UnlockRange
関数などの GetPosition
メンバー関数はサポートされていません。 CSocketFile オブジェクトは、関連付けられている CSocket
オブジェクトとの間でバイトシーケンスを書き込むか読み取る必要があります。 ファイルは関係しないため、 Seek
や GetPosition
などの操作は意味をなしません。 CSocketFile
は CFile
から派生しているため、通常、これらのメンバー関数はすべて継承されます。 これを防ぐために、サポートされていないCFile
メンバー関数は、CSocketFile
をスローするためにでオーバーライドされます。
CSocketFile
オブジェクトは、CSocket
オブジェクトのメンバー関数を呼び出して、データを送受信します。
次の図は、通信の両側にあるこれらのオブジェクト間の関係を示しています。
CArchive、CSocketFile、および CSocket
この明らかな複雑さの目的は、ソケットの詳細を自分で管理する必要からあなたを保護することです。 ソケット、ファイル、アーカイブを作成し、アーカイブに挿入するかアーカイブからデータを抽出して、データの送受信を開始します。 CArchive、 CSocketFile、 および 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 ソケット: アーカイブでのソケットの使用」を参照してください。