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
の同期操作に不可欠です。 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 ソケット: アーカイブでのソケットの使用」を参照してください。