Использование IcmpSendEcho2 с асинхронным обратным вызовом - PullRequest
0 голосов
/ 26 января 2011

Я читал документацию MSDN для IcmpSendEcho2 , и это вызывает больше вопросов, чем ответов.

Я знаком с асинхронными обратными вызовами из других Win32 API, таких как ReadFileEx ... Я предоставляю буфер, который, я гарантирую, будет зарезервирован для использования драйвером, пока операция не завершится с любым результатом, отличным от IO_PENDING. получить мой обратный вызов в случае успеха или неудачи (и позвонить GetCompletionStatus, чтобы узнать, какой). Тайм-ауты - моя ответственность, и я могу вызвать CancelIo, чтобы прервать обработку, но буфер остается зарезервированным, пока драйвер не отменит операцию и не вызовет мою процедуру завершения со статусом CANCELLED. И есть структура OVERLAPPED, которая однозначно идентифицирует запрос через все это.

IcmpSendEcho2 не использует структуру контекста OVERLAPPED для асинхронных запросов. И документация неясна чрезмерно минималистична о том, что произойдет, если пинг истечет или произойдет сбой (сбой будет из-за отсутствия сетевого подключения, отсутствующей записи ARP для локальных узлов, ICMP-адресата недоступен ответ от промежуточного маршрутизатора для удаленных узлов и т. д.).

Кто-нибудь знает, происходит ли обратный вызов по истечении времени ожидания и / или сбоя? И особенно, если ответ не приходит, могу ли я повторно использовать буфер для другого вызова IcmpSendEcho2 или он навсегда зарезервирован на случай, если ответ приходит с опозданием?

Я хочу использовать эту функцию из службы Win32, что означает, что я должен правильно обрабатывать случаи обработки ошибок, и я не могу просто использовать утечку буферов (или, если API действительно делает утечки буферов, я должен использовать вспомогательный процесс, поэтому у меня есть способ отказаться от запросов).

Существует также ужасная несовместимость в способе обратного вызова. Похоже, что первый параметр согласован между двумя сигнатурами, поэтому я должен иметь возможность использовать более новый PIO_APC_ROUTINE, если только я использую второй параметр, если проверка версии ОС возвращает Vista или новее? Хотя MSDN говорит «не проверять версию Windows», мне кажется, что мне нужно, потому что набор версий с новым аргументом не совпадает с набором версий, в которых функция существует в iphlpapi.dll.

Указатели на дополнительную документацию или рабочий код, который использует эту функцию и APC, будут очень благодарны.

Пожалуйста, также дайте мне знать, если это совершенно неправильный подход, т. Е. Если бы использование сырых сокетов или какой-либо комбинации IcmpCreateFile + WriteFileEx + ReadFileEx было бы более надежным.

1 Ответ

1 голос
/ 14 марта 2011

Я использую IcmpSendEcho2 с событием, а не с обратным вызовом, но я думаю, что поток одинаков в обоих случаях. IcmpSendEcho2 использует NtDeviceIoControlFile внутри. Он обнаруживает некоторые ошибки, связанные с ICMP, на ранних этапах и возвращает их в виде кодов ошибок в диапазоне 12xx. Если (и только если) IcmpSendEcho2 вернет ERROR_IO_PENDING, он в конечном итоге вызовет обратный вызов и / или установит событие независимо от того, , будет ли пинг успешен, неуспешен или истечет время ожидания. Любые буферы, которые вы передаете, должны быть сохранены до тех пор, но впоследствии могут быть использованы повторно.

Что касается проверки версии, ее можно избежать за небольшую плату, используя событие с RegisterWaitForSingleObject вместо обратного вызова APC.

...