CSocketFile クラス
Windows ソケットを使ったネットワーク間でのデータの送受信に使われる CFile
オブジェクトです。
構文
class CSocketFile : public CFile
メンバー
パブリック コンストラクター
名前 | 説明 |
---|---|
CSocketFile::CSocketFile | CSocketFile オブジェクトを構築します。 |
解説
この目的のために、 CSocketFile
オブジェクトを CSocket
オブジェクトにアタッチできます。 また、MFC シリアル化を使用してデータの送受信を簡略化するために、 CSocketFile
オブジェクトを CArchive
オブジェクトにアタッチすることもできます。通常は、これを行います。
データをシリアル化 (送信) するには、アーカイブにデータを挿入し、 CSocketFile
メンバー関数を呼び出して CSocket
オブジェクトにデータを書き込みます。 データを逆シリアル化 (受信) するには、アーカイブから抽出します。 これにより、アーカイブ CSocketFile
メンバー関数が呼び出され、 CSocket
オブジェクトからデータが読み取られます。
ヒント
ここで説明するように CSocketFile
を使用するだけでなく、 CFile
の基底クラスと同様に、スタンドアロン ファイル オブジェクトとして使用できます。 アーカイブ ベースの MFC シリアル化関数で CSocketFile
を使用することもできます。 CSocketFile
はCFile
のすべての機能をサポートしているわけではないため、一部の既定の MFC シリアル化関数はCSocketFile
と互換性がありません。 これは、CEditView
クラスに特に当てはまります。 CEditView::SerializeRaw
を使用して、CSocketFile
オブジェクトにアタッチされたCArchive
オブジェクトを介してCEditView
データをシリアル化しないでください。代わりにCEditView::Serialize
を使用してください。 SerializeRaw
関数は、ファイル オブジェクトに、CSocketFile
に含まれていない関数 (Seek
など) があることを想定しています。
CSocketFile
とCSocket
でCArchive
を使用すると、CSocket::Receive
が要求されたバイト数を待機するループ (PumpMessages(FD_READ)
) に入る状況が発生する可能性があります。 これは、Windows ソケットでは、FD_READ通知ごとに 1 つの recv 呼び出ししか許可されませんが、 CSocketFile
と CSocket
では、FD_READごとに複数の recv 呼び出しが許可されるためです。 読み取るデータがないときにFD_READが発生すると、アプリケーションがハングします。 別のFD_READが取得されない場合、アプリケーションはソケット経由で通信を停止します。
この問題は、次のように解決できます。 ソケット クラスの OnReceive
メソッドで、ソケットから読み取られる予想されるデータが 1 つの TCP パケットのサイズ (通常は 1096 バイト以上) を超えたときに、メッセージ クラスのSerialize
メソッドを呼び出す前に、CAsyncSocket::IOCtl(FIONREAD, ...)
を呼び出します。 使用可能なデータのサイズが必要未満の場合は、すべてのデータが受信されるのを待ってから、読み取り操作を開始します。
次の例では、 m_dwExpected
は、ユーザーが受け取る予定のおおよそのバイト数です。 コード内の他の場所で宣言することを前提としています。
void CChatSocket::OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
DWORD dwReceived;
if (IOCtl(FIONREAD, &dwReceived))
{
if (dwReceived >= m_dwExpected) // Process only if you have enough data
m_pDoc->ProcessPendingRead();
}
else
{
// Error handling here
}
}
詳細については、「
継承階層
CSocketFile
要件
Header: afxsock.h
CSocketFile::CSocketFile
CSocketFile
オブジェクトを構築します。
explicit CSocketFile(
CSocket* pSocket,
BOOL bArchiveCompatible = TRUE);
パラメーター
pSocket
CSocketFile
オブジェクトにアタッチするソケット。
bArchiveCompatible
ファイル オブジェクトを CArchive
オブジェクトで使用するかどうかを指定します。 スタンドアロン CFile
オブジェクトと同様に、CSocketFile
オブジェクトをスタンドアロンの方法で使用する場合にのみ FALSE を渡します。一部の制限があります。 このフラグは、CSocketFile
オブジェクトにアタッチされているCArchive
オブジェクトが読み取り用のバッファーを管理する方法を変更します。
解説
オブジェクトのデストラクターは、オブジェクトがスコープ外になったり削除されたりすると、ソケット オブジェクトとの関連付けを解除します。
Note
CSocketFile
は、CArchive
オブジェクトを含まない (制限付き) ファイルとして使用することもできます。 既定では、 CSocketFile
コンストラクターの bArchiveCompatible パラメーターは TRUE です。 これは、ファイル オブジェクトがアーカイブで使用するためのものであることを示します。 アーカイブなしでファイル オブジェクトを使用するには、 bArchiveCompatible パラメーターに FALSE を渡します。
"アーカイブ互換" モードでは、 CSocketFile
オブジェクトのパフォーマンスが向上し、"デッドロック" の危険性が軽減されます。デッドロックは、送信側と受信側の両方のソケットが互いに待機しているとき、または共通リソースを待機しているときに発生します。 この状況は、CArchive
オブジェクトが CFile
オブジェクトと連動するように CSocketFile
と連動した場合に発生する可能性があります。 CFile
を使用した場合は、アーカイブで、要求したバイト数より少ないバイト数を受信したときに、ファイルの終わりに達したと見なすことができます。
ただし、CSocketFile
を使用した場合は、データがメッセージ ベースになり、バッファーに複数のメッセージが含まれている可能性があるため、要求したバイト数より少ないバイト数を受信しても、ファイルの終わりと見なすことができません。 この場合は、CFile
を使用した場合と同様にアプリケーションがブロックしません。バッファーが空になるまで、バッファーからのメッセージの読み取りを継続できます。 CArchive::IsBufferEmpty 関数は、このような場合にアーカイブのバッファーの状態を監視するのに役立ちます。
CSocketFile
の使用方法の詳細については、「Windows ソケット: アーカイブでのソケットの使用およびWindows ソケット: アーカイブを使用するソケットの例に関する記事を参照してください。