2017-01-19 3 views
1

Я пишу код Win32-API C, которому нужно дождаться новых TCP-соединений, а с другой стороны можно в любой момент закрыть любым другим процессом/потоком.Windows - Подождите, когда событие и гнездо будут симулированы

Поэтому мне нужно как-то WaitForSingleObject в событии остановки и ждать соединений, используя WSAAccept одновременно.

Я пробовал WaitForMultipleObjects как в сокете, так и в дескрипторе, но новое соединение не вызывает функцию (также WaitForSingleObject в сокете не будет запускаться при новом соединении).

Есть идеи?

+1

вам нужно использовать [AcceptEx] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms737524 (v = vs.85) .aspx) вместо 'WSAAccept' - этот апикс асинхронный , вам не нужно ждать на нем вообще. если вы связываете сокет (второй параметр) с 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

Это позволит вам ждать событий WSA-сокета, а не стандартных объектов событий Win32, поэтому вам нужно будет использовать событие WSA-сокета для события остановки, то вы можете ожидать от всех событий вместе с 'WSAWaitForMultipleEvents()'. Если вы хотите использовать стандартный объект события для события stop, вам необходимо использовать Overlapped I/O или IOCP для операций сокета ('AcceptEx()', 'WSARecv()', 'WSASend()' и т. Д.), поэтому вы можете назначать стандартные события событий для каждой операции, а затем вы можете использовать 'WaitForMultipleObjects()'. –

+1

Массив событий для WSAWaitForMultipleEvents может обрабатывать несколько типов («Массив может содержать дескрипторы объектов разных типов» - это то, что говорится в документации). Документация WSACreateEvent добавляет: «если приложение Windows хочет использовать событие автоматического сброса, а не событие с ручным сбросом, приложение может напрямую вызвать функцию CreateEvent». –

1

Вы не можете ждать непосредственно на ручках сокетов.

WSAAccept() является синхронным, единственный способ прервать его - закрыть гнездо для прослушивания.

Для того, что вы пытаетесь сделать, вместо этого используйте AcceptEx(), который является асинхронным и поддерживает операции перекрытия ввода-вывода и ввода-вывода ввода-вывода.

Если вы используете Overlapped I/O, вы можете связать стандартный объект события Win32 для каждого Overlapped I/O способны гнезда (AcceptEx(), WSARecv(), WSASend() и т.д.), а также использовать стандартный объект события Win32 для остановки события , И затем вы можете использовать цикл WaitForMultipleObjects(), чтобы узнать, какое событие (ы) сигнализируется и действует соответствующим образом.

Если вы используете порт завершения ввода-вывода, вам вообще не нужны объекты событий. Вы можете связать каждый сокет с одной очередью IOCP, и ваш обработчик IOCP (либо вызов GetQueuedCompletionStatus(), либо функция обратного вызова) будет уведомляться всякий раз, когда завершается каждая операция сокета IOCP. Затем вы можете использовать PostQueuedCompletionStatus() для отправки пользовательского сообщения остановки в очередь IOCP. Ваш обработчик IOCP может действовать соответствующим образом, исходя из того, какое событие он получает.

+0

'использовать PostQueuedCompletionStatus() для отправки пользовательского сообщения остановки в очередь IOCP' - мы можем связать сокет с обработанной системой операцией' BindIoCompletionCallback' или 'CreateThreadpoolIo' - эту очередь не нужно останавливать и иметь собственный обработчик.однако, если использовать самосозданный IOCP - несколько рабочих потоков необходимо создать для обработки этого IOCP (обычное число потоков == количество процессоров) - поэтому нужно вызывать 'PostQueuedCompletionStatus' не один раз, а количество потоков - для уведомления о каждом потоке для остановки. – RbMm