次の方法で共有


CSocketFile クラス

Windows ソケットを使ったネットワーク間でのデータの送受信に使われる CFile オブジェクトです。

構文

class CSocketFile : public CFile

メンバー

パブリック コンストラクター

名前 説明
CSocketFile::CSocketFile CSocketFile オブジェクトを構築します。

解説

この目的のために、 CSocketFile オブジェクトを CSocket オブジェクトにアタッチできます。 また、MFC シリアル化を使用してデータの送受信を簡略化するために、 CSocketFile オブジェクトを CArchive オブジェクトにアタッチすることもできます。通常は、これを行います。

データをシリアル化 (送信) するには、アーカイブにデータを挿入し、 CSocketFile メンバー関数を呼び出して CSocket オブジェクトにデータを書き込みます。 データを逆シリアル化 (受信) するには、アーカイブから抽出します。 これにより、アーカイブ CSocketFile メンバー関数が呼び出され、 CSocket オブジェクトからデータが読み取られます。

ヒント

ここで説明するように CSocketFile を使用するだけでなく、 CFileの基底クラスと同様に、スタンドアロン ファイル オブジェクトとして使用できます。 アーカイブ ベースの MFC シリアル化関数で CSocketFile を使用することもできます。 CSocketFileCFileのすべての機能をサポートしているわけではないため、一部の既定の MFC シリアル化関数はCSocketFileと互換性がありません。 これは、CEditView クラスに特に当てはまります。 CEditView::SerializeRawを使用して、CSocketFile オブジェクトにアタッチされたCArchive オブジェクトを介してCEditViewデータをシリアル化しないでください。代わりにCEditView::Serializeを使用してください。 SerializeRaw関数は、ファイル オブジェクトに、CSocketFileに含まれていない関数 (Seekなど) があることを想定しています。

CSocketFileCSocketCArchiveを使用すると、CSocket::Receiveが要求されたバイト数を待機するループ (PumpMessages(FD_READ)) に入る状況が発生する可能性があります。 これは、Windows ソケットでは、FD_READ通知ごとに 1 つの recv 呼び出ししか許可されませんが、 CSocketFileCSocket では、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
   }
}

詳細については、「Windows Sockets in MFCWindows Sockets: Using Sockets with Archives、および Windows Sockets 2 APIを参照してください。

継承階層

CObject

CFile

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 ソケット: アーカイブを使用するソケットの例に関する記事を参照してください。

関連項目

CFile クラス
階層図
CAsyncSocket クラス
CSocket クラス