Вы предлагаете два способа выполнения перекрывающихся операций ввода-вывода и игнорируете третий (или я неправильно понимаю ваш вопрос).
Когда вы выполняете перекрытую операцию, например WSARecv () , вы можете указать структуру OVERLAPPED, которая содержит событие, и вы можете подождать, пока это событие будет сигнализировано, чтобы указать перекрывающийся ввод-вывод завершено. Я предполагаю, что это ваш подход WaitForMultipleObjects (), и, как упоминалось ранее, он не очень хорошо масштабируется, так как вы ограничены количеством дескрипторов, которые вы можете передать WaitForMultipleObjects ().
В качестве альтернативы вы можете пройти процедуру завершения, которая вызывается, когда происходит завершение. Это известно как «тревожный ввод-вывод» и требует, чтобы поток, который выполнил вызов WSARecv (), находился в состоянии «оповещения» для вызова процедуры завершения. Потоки могут переводить себя в состояние тревоги несколькими способами (вызывая SleepEx () или различные EX-функции функций Wait и т. Д.). Книга Рихтера , которую я открываю передо мной, гласит: «Я немного поработал с оповещаемым вводом / выводом, и я буду первым, кто скажет вам, что оповещаемый ввод / вывод ужасен и должен избегать". Хватит говорить ИМХО.
Существует третий способ, перед тем как выполнить вызов, вы должны связать дескриптор, на котором вы хотите сделать перекрытый ввод-вывод, с портом завершения. Затем вы создаете пул потоков, которые обслуживают этот порт завершения, вызывая GetQueuedCompletionStatus () и цикл. Вы выдаете свой WSARecv () со структурой OVERLAPPED БЕЗ события в нем, и после завершения ввода-вывода завершение выскакивает из GetQueuedCompletionStatus () в одном из потоков пула ввода-вывода и может обрабатываться там.
Как уже упоминалось ранее, Vista / Server 2008 немного очистил работу IOCP и устранил проблему, благодаря которой вы должны были убедиться, что поток, который выдал перекрывающийся запрос, продолжал работать до тех пор, пока запрос не будет завершен. Ссылку на ссылку можно найти здесь . Но эту проблему легко обойти в любом случае; вы просто перенаправляете WSARecv в один из потоков вашего пула ввода-вывода, используя тот же IOCP, который вы используете для завершения ...
В любом случае, ИМХО использование IOCP - лучший способ сделать перекрывающийся ввод / вывод. Да, чтобы разобраться с перекрывающейся / асинхронной природой вызовов, вначале может потребоваться немного времени, но это того стоит, поскольку система очень хорошо масштабируется и предлагает простой метод «запускай и забывай» для работы с перекрывающимися операциями.
Если вам нужен пример кода для начала работы, у меня есть несколько статей по написанию систем портов завершения ввода-вывода и куча бесплатного кода, который обеспечивает реальную среду для высокопроизводительных серверов; см. здесь .
в сторону; ИМХО, вам действительно следует прочесть « Windows Via C / C ++ (PRO-Developer) » Джеффри Рихтера и Кристофа Насарре, так как там написано все, что вам нужно знать о перекрывающихся операциях ввода-вывода и большинстве других современных платформ Windows. методы и API.