次の方法で共有


CSocket クラス

CAsyncSocketから派生し、Windows ソケット API のカプセル化を継承し、CAsyncSocket オブジェクトの抽象化よりも高いレベルの抽象化を表します。

構文

class CSocket : public CAsyncSocket

メンバー

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

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

パブリック メソッド

名前 説明
CSocket::Attach CSocket オブジェクトにSOCKET ハンドルをアタッチします。
CSocket::CancelBlockingCall 現在進行中のブロック呼び出しを取り消します。
CSocket::Create ソケットを作成します。
CSocket::FromHandle SOCKET ハンドルを指定して、CSocket オブジェクトへのポインターを返します。
CSocket::IsBlocking ブロック呼び出しが進行中かどうかを判断します。

保護メソッド

名前 説明
CSocket::OnMessagePending ブロック呼び出しの完了を待機している間に保留中のメッセージを処理するために呼び出されます。

解説

CSocket は、データの送受信を管理するために CSocketFile および CArchive クラスと連携します。

CSocket オブジェクトはブロックも提供します。これは、CArchiveの同期操作に不可欠です。 ReceiveSendReceiveFromSendToAccept (すべて CAsyncSocket から継承) などのブロッキング関数は、CSocketWSAEWOULDBLOCKエラーを返しません。 代わりに、これらの関数は操作が完了するまで待機します。 さらに、これらの関数のいずれかがブロックされている間に CancelBlockingCall が呼び出されると、元の呼び出しはエラー WSAEINTR で終了します。

CSocket オブジェクトを使用するには、コンストラクターを呼び出し、Createを呼び出して、基になるSOCKET ハンドル (型SOCKET) を作成します。 Createの既定のパラメーターはストリーム ソケットを作成しますが、CArchive オブジェクトでソケットを使用していない場合は、代わりにデータグラム ソケットを作成するパラメーターを指定するか、特定のポートにバインドしてサーバー ソケットを作成できます。 クライアント側で Connect を使用してクライアント ソケットに接続し、サーバー側で Accept します。 次に、CSocketFile オブジェクトを作成し、CSocketFile コンストラクターのCSocket オブジェクトに関連付けます。 次に、送信用のCArchive オブジェクトとデータを受信するオブジェクト (必要に応じて) を作成し、それらをCArchive コンストラクターのCSocketFile オブジェクトに関連付けます。 通信が完了したら、 CArchiveCSocketFile、および CSocket オブジェクトを破棄します。 SOCKETデータ型については、「Windows ソケット: 背景」の記事で説明

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
   }
}

Note

静的にリンクされた MFC アプリケーションのセカンダリ スレッドで MFC ソケットを使用する場合は、ソケットを使用してソケット ライブラリを初期化する各スレッドで AfxSocketInit を呼び出す必要があります。 既定では、 AfxSocketInit はプライマリ スレッドでのみ呼び出されます。

詳細については、「Windows Sockets in MFCWindows Sockets: Using Sockets with ArchivesWindows Sockets: How Sockets with archives(アーカイブを使用したソケットの動作)、 Windows ソケット: 操作シーケンス、Windows ソケット: アーカイブを使用したソケットの例を参照してください。

継承階層

CObject

CAsyncSocket

CSocket

要件

ヘッダー: afxsock.h

CSocket::Attach

このメンバー関数を呼び出して、 hSocket ハンドルを CSocket オブジェクトにアタッチします。

BOOL Attach(SOCKET hSocket);

パラメーター

hSocket
ソケットへのハンドルを格納します。

戻り値

正常終了した場合は 0 以外を返します。

解説

SOCKET ハンドルは、オブジェクトのm_hSocket データ メンバーに格納されます。

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

class CSockThread : public CWinThread
{
public:
   SOCKET m_hConnected;

protected:
   CChatSocket m_sConnected;

   // remainder of class declaration omitted.

 

BOOL CSockThread::InitInstance()
{
   // Attach the socket object to the socket handle
   // in the context of this thread.
   m_sConnected.Attach(m_hConnected);
   m_hConnected = NULL;

   return TRUE;
}

 

// This listening socket has been constructed
// in the primary thread.
void CListeningSocket::OnAccept(int nErrorCode)
{
   UNREFERENCED_PARAMETER(nErrorCode);

   // This CSocket object is used just temporarily
   // to accept the incoming connection.
   CSocket sConnected;
   Accept(sConnected);

   // Start the other thread.
   CSockThread *pSockThread = (CSockThread*)AfxBeginThread(
       RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
   if (NULL != pSockThread)
   {
      // Detach the newly accepted socket and save
      // the SOCKET handle in our new thread object.
      // After detaching it, it should no longer be
      // used in the context of this thread.
      pSockThread->m_hConnected = sConnected.Detach();
      pSockThread->ResumeThread();
   }
}

CSocket::CancelBlockingCall

現在進行中のブロック呼び出しを取り消すには、このメンバー関数を呼び出します。

void CancelBlockingCall();

解説

この関数は、このソケットの未処理のブロック操作を取り消します。 元のブロッキング呼び出しは、エラー WSAEINTRでできるだけ早く終了します。

ブロック Connect 操作の場合、Windows ソケットの実装はできるだけ早くブロック呼び出しを終了しますが、接続が完了 (リセットされた後) またはタイムアウトになるまでソケット リソースを解放できない場合があります。これは、アプリケーションがすぐに新しいソケットを開こうとした場合 (使用可能なソケットがない場合)、または同じピアに接続しようとした場合にのみ顕著になる可能性があります。

Accept以外の操作を取り消しても、ソケットが不確定な状態になる可能性があります。 アプリケーションがソケットでブロック操作を取り消した場合、アプリケーションがソケットで実行できることに依存できる唯一の操作は、 Closeの呼び出しですが、他の操作は一部の Windows ソケット実装で動作する可能性があります。 アプリケーションの移植性を最大限に高める必要がある場合は、キャンセル後の操作の実行に依存しないように注意する必要があります。

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

CSocket::Create

ソケット オブジェクトを作成して Windows ソケットを作成してアタッチした後、 Create メンバー関数を呼び出します。

BOOL Create(
    UINT nSocketPort = 0,
    int nSocketType = SOCK_STREAM,
    LPCTSTR lpszSocketAddress = NULL);

パラメーター

nSocketPort
ソケットで使用する特定のポート。MFC でポートを選択する場合は 0。

nSocketType
SOCK_STREAM または SOCK_DGRAM

lpszSocketAddress
接続されているソケットのネットワーク アドレスを含む文字列へのポインター。"128.56.22.8" などのドット番号。 このパラメーターに NULL 文字列を渡すと、 CSocket インスタンスはすべてのネットワーク インターフェイスでクライアント アクティビティをリッスンする必要があることを示します。

戻り値

関数が成功した場合は 0 以外。それ以外の場合は 0 で、 GetLastErrorを呼び出すことによって特定のエラー コードを取得できます。

解説

Create 次に、 Bind を呼び出して、ソケットを指定したアドレスにバインドします。 次のソケットの種類がサポートされています。

  • SOCK_STREAM シーケンス化された信頼性の高い双方向の接続ベースのバイト ストリームを提供します。 インターネット アドレス ファミリに伝送制御プロトコル (TCP) を使用します。

  • SOCK_DGRAM 固定 (通常は小さい) 最大長のコネクションレスで信頼性の低いバッファーであるデータグラムをサポートします。 インターネット アドレス ファミリにユーザー データグラム プロトコル (UDP) を使用します。 このオプションを使用するには、 CArchive オブジェクトでソケットを使用しないでください。

    Note

    Accept メンバー関数は、新しい空の CSocket オブジェクトへの参照をパラメーターとして受け取ります。 Accept を呼び出す前に、このオブジェクトを構築する必要があります。 このソケット オブジェクトがスコープ外になると、接続が閉じられることに注意してください。 この新しいソケット オブジェクトに対して Create を呼び出さないでください。

ストリーム ソケットとデータグラム ソケットの詳細については、「<Windows ソケット: 背景Windows ソケット: ポートとソケット アドレス、および Windows ソケット: アーカイブでのソケットの使用に関する記事を参照してください。

CSocket::CSocket

CSocket オブジェクトを構築します。

CSocket();

解説

構築後、 Create メンバー関数を呼び出す必要があります。

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

CSocket::FromHandle

CSocket オブジェクトへのポインターを返します。

static CSocket* PASCAL FromHandle(SOCKET hSocket);

パラメーター

hSocket
ソケットへのハンドルを格納します。

戻り値

CSocket オブジェクトへのポインター。または、hSocketにアタッチされているCSocket オブジェクトがない場合にNULLします。

解説

SOCKET ハンドルが指定されると、CSocket オブジェクトがハンドルにアタッチされていない場合、メンバー関数はNULLを返し、一時オブジェクトは作成しません。

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

CSocket::IsBlocking

このメンバー関数を呼び出して、ブロック呼び出しが進行中かどうかを判断します。

BOOL IsBlocking();

戻り値

ソケットがブロックしている場合は 0 以外。それ以外の場合は 0。

解説

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

CSocket::OnMessagePending

このメンバー関数をオーバーライドして、Windows から特定のメッセージを検索し、ソケットでそれらに応答します。

virtual BOOL OnMessagePending();

戻り値

メッセージが処理された場合は 0 以外。それ以外の場合は 0。

解説

これは、高度なオーバーライドが可能です。

このフレームワークは、ソケットが Windows メッセージをポンプしている間に OnMessagePending を呼び出して、アプリケーションに関心のあるメッセージを処理する機会を提供します。 OnMessagePendingの使用方法の例については、「Windows ソケット: ソケット クラスからの派生」を参照してください。

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

関連項目

CAsyncSocket クラス
階層図
CAsyncSocket クラス
CSocketFile クラス