2017-01-19 22 views
1

新しいTCP接続を待つ必要のあるWin32-API Cコードを書いています。他のプロセスやスレッドはいつでも閉じることができます。Windows - イベントとソケットを同時に待機する

したがって、私は何とかstopイベントでWaitForSingleObjectを必要とし、同時にWSAAcceptを使用して接続を待つ必要があります。

ソケットとハンドルの両方でWaitForMultipleObjectsを試しましたが、新しい接続では関数がトリガーされません(ソケット上のWaitForSingleObjectは新しい接続ではトリガーされません)。

+1

代わりに[AcceptEx](https://msdn.microsoft.com/en-us/library/windows/desktop/ms737524(v = vs.85).aspx)を使用する必要があります。「WSAAccept」 - このAPIは非同期です。あなたはそれをまったく待つ必要はありません。ソケット(2番目のパラメータ)をIOCPにバインドすると、接続が完了したときにコールバックを受け取る – RbMm

答えて

2

WSAWaitForMultipleEventsを使用する必要があります。あなたが複数のイベントを使用している場合

HANDLE hEvent[1]; 
hEvent[0] = WSACreateEvent(); 
WSAEventSelect(hSocket, hEvent[0], FD_READ | FD_WRITE); 

while (WSAWaitForMultipleEvents(...)) { 
    if (WSAEnumNetworkEvents(...)) { // Multiple events max exist 
     if (... & FD_ACCEPT) { 
     } 
     if (... & FD_WRITE) { 
     } 
     .... 
    } 
} 

(例えば停止イベントが停止するスレッドを知らせるために)あなたがそうであるように、(シグナルイベントを決定するためにWSAWaitForMultipleEventsからの戻り値を使用します。ソケットの場合、ここにいくつかの擬似コードですWaitForMultipleObjects)。

+1

これは、標準Win32イベントオブジェクトではなくWSAソケットイベントで待機することができるため、ストップイベントにWSAソケットイベントを使用する必要があり、 'WSAWaitForMultipleEvents()'と一緒にすべてのイベントを待つことができます。 stopイベントに標準のイベントオブジェクトを使用する場合は、ソケット操作( 'AcceptEx()'、 'WSARecv()'、 'WSASend()'など)にオーバーラップI/OまたはIOCPを使用する必要があります。標準的なイベントオブジェクトを各操作に割り当てることができます。そして、あなたは 'WaitForMultipleObjects()'を使うことができます。 –

+1

WSAWaitForMultipleEventsのevents配列は、複数の型を扱うことができます( '配列にはさまざまな型のオブジェクトのハンドルを含めることができます'というドキュメントです)。 WSACreateEventのドキュメントでは、 'Windowsアプリケーションが手動リセットイベントではなく自動リセットイベントを使用する場合、アプリケーションはCreateEvent関数を直接呼び出すことができます'。 –

1

ソケットハンドルを直接待つことはできません。

WSAAccept()は同期ですが、中止する唯一の方法はリスニングソケットを閉じることです。

代わりに、AcceptEx()を使用してください。これは非同期で、オーバーラップI/OとI/O完了ポートをサポートしています。

あなたが重複したI/Oを使用する場合は、それぞれ重複したI/Oが可能なソケット操作(AcceptEx()WSARecv()WSASend()、など)に標準のWin32イベントオブジェクトを関連付け、そしてあなたの停止イベントのための標準のWin32イベントオブジェクトを使用することができます。次に、WaitForMultipleObjects()ループを使用して、どのイベントが通知され、それに応じて動作するかを知ることができます。

I/O完了ポートを使用する場合、イベントオブジェクトはまったく必要ありません。各ソケットを単一のIOCPキューに関連付けることができ、各IOCP対応ソケット操作が完了するたびにIOCPハンドラ(GetQueuedCompletionStatus()またはコールバック関数の呼び出し)が通知されます。 PostQueuedCompletionStatus()を使用して、カスタム停止メッセージをIOCPキューに送信できます。 IOCPハンドラは、受信するイベントの種類に応じて動作することができます。

+0

'PostQueuedCompletionStatus()を使用してカスタム停止メッセージをIOCPキューにポストする' - 'BindIoCompletionCallback'または' CreateThreadpoolIo'でソケットをシステム処理キューにバインドすることができます。しかし、IOCPを作成した場合、いくつかの作業スレッドはこのIOCP(通常のスレッド数==プロセッサ数)を処理するために作成する必要があるので、 'PostQueuedCompletionStatus'を一度ではなく、スレッド数で呼び出す必要があります。 – RbMm

関連する問題