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の同期操作に不可欠です。 Receive、Send、ReceiveFrom、SendTo、Accept (すべて CAsyncSocket から継承) などのブロッキング関数は、CSocketでWSAEWOULDBLOCKエラーを返しません。 代わりに、これらの関数は操作が完了するまで待機します。 さらに、これらの関数のいずれかがブロックされている間に CancelBlockingCall が呼び出されると、元の呼び出しはエラー WSAEINTR で終了します。
CSocket オブジェクトを使用するには、コンストラクターを呼び出し、Createを呼び出して、基になるSOCKET ハンドル (型SOCKET) を作成します。 Createの既定のパラメーターはストリーム ソケットを作成しますが、CArchive オブジェクトでソケットを使用していない場合は、代わりにデータグラム ソケットを作成するパラメーターを指定するか、特定のポートにバインドしてサーバー ソケットを作成できます。 クライアント側で Connect を使用してクライアント ソケットに接続し、サーバー側で Accept します。 次に、CSocketFile オブジェクトを作成し、CSocketFile コンストラクターのCSocket オブジェクトに関連付けます。 次に、送信用のCArchive オブジェクトとデータを受信するオブジェクト (必要に応じて) を作成し、それらをCArchive コンストラクターのCSocketFile オブジェクトに関連付けます。 通信が完了したら、 CArchive、 CSocketFile、および CSocket オブジェクトを破棄します。 SOCKETデータ型については、「Windows ソケット: 背景」の記事で説明。
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
}
}
Note
静的にリンクされた MFC アプリケーションのセカンダリ スレッドで MFC ソケットを使用する場合は、ソケットを使用してソケット ライブラリを初期化する各スレッドで AfxSocketInit を呼び出す必要があります。 既定では、 AfxSocketInit はプライマリ スレッドでのみ呼び出されます。
詳細については、「
継承階層
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を呼び出さないでください。
ストリーム ソケットとデータグラム ソケットの詳細については、「<
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 ソケット: アーカイブでのソケットの使用」を参照してください。