Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.01.2017, 11:40   #1
Sabre
Пользователь
 
Регистрация: 13.09.2016
Сообщений: 16
По умолчанию Асинхронный пинг

IcmpSendEcho2 позволяет делать асинхронные запросы как Event (второй параметр функции) или как через Callback функцию (третий параметр).

Сделал всё как по статье из MSDN, через PIO_APC_ROUTINE, но этот самый ROUTINE никак не хотел вызываться. Убил полдня, чтобы в поисках ошибки, но, как оказалось, ошибки нет.

Asynchronous Procedure Calls:
Цитата:
When a user-mode APC is queued, the thread to which it is queued is not directed to call the APC function unless it is in an alertable state. A thread enters an alertable state when it calls the SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx, or WaitForSingleObjectEx function.
Почему-то в статье по IcmpSendEcho2 об этом ни слова нет, пришлось доходить самому. Чтобы вызвалась ROUTINE необходимо в код добавить одну из вышеприведённых фунций. Проверил - работает. Добавил SleepEx(0, TRUE); после IcmpSendEcho2, ROUTINE успешно вызывается, НО! Условный код:
Код:
main() {
    HANDLE hIcmp = IcmpCreateFile();
    IcmpSendEcho2(hIcmp, 0, callback, ...); // - тут заведомо непигнующийся хост
    SleepEx(0, TRUE);
    printf("123");
}

callback(...) {
    printf("321");
}
При запуске такое приложение зависнет, пока не будет получено, что удалённый хост не отвечает, потом сначала напечатает "321", затем "123".

При этом полностью теряется вся асинхронность. SleepEx ставит приложение на паузу до тех пор, пока не будет получен ответ от IcmpSendEcho2.

Если создавать отдельный тред, под каждый пинг, то получится очень много накладных расходов (пинговаться могут сотни хостов параллельно). Может я что-то упустил или делаю не так? Или всё-таки единственным методом асинхронности будет использование Event-ов?
Sabre вне форума Ответить с цитированием
Старый 30.01.2017, 11:54   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Берете WaitForSingleObjectEx с маленьким таймаутом (или 0 ) и в цикле проверяете. Виснуть не будет.
p51x вне форума Ответить с цитированием
Старый 30.01.2017, 12:45   #3
Sabre
Пользователь
 
Регистрация: 13.09.2016
Сообщений: 16
По умолчанию

Поменял SleepEx на WaitForSingleObjectEx - ситуация с зависонами не поменялась, но Callback функция вызываться перестала. За наводку спасибо, меня осенило и я понял в чём проблема:
Цитата:
main() {
HANDLE hIcmp = IcmpCreateFile();
IcmpSendEcho2(hIcmp, 0, callback, ...); // - тут заведомо непигнующийся хост
SleepEx(0, TRUE);
IcmpCloseHandle(hIcmp);
printf("123");
}

callback(...) {
printf("321");
}
Т.е., по всей видимости, зависон случается не на SleepEx, как я предположил, а во время закрытия хендла hIcmp - он просто не закрывается и блочит программу пока Callback функция не выполнится. Момент, на который я настолько не обратил внимания, что даже не включил его в мой условный код. Вероятно, правильно будет открыть и сохранить этот хендл где-то в начале приложения, использовать, и закрыть при выходе из приложения (или даже он сам убьётся при ExitProcess).
Sabre вне форума Ответить с цитированием
Старый 30.01.2017, 13:03   #4
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Таймаут какой ставили? Параметры вызовы в студию!

Цитата:
Т.е., по всей видимости, зависон случается не на SleepEx, как я предположил, а во время закрытия хендла hIcmp - он просто не закрывается и блочит программу пока Callback функция не выполнится.
Да снизойдет на вас просвещение... А как, по вашему, система могла его закрыть, если он активен и вы его не отменили?
p51x вне форума Ответить с цитированием
Старый 30.01.2017, 13:29   #5
Sabre
Пользователь
 
Регистрация: 13.09.2016
Сообщений: 16
По умолчанию

Вызывал так:
Код:
IcmpSendEcho2(hIcmp, 0, (PIO_APC_ROUTINE)IcmpCallback, host, inet_addr(host), echo.IcmpData, sizeof(echo.IcmpData), 0, &echo, sizeof(echo)+8, 4000);
А такой косяк у меня от нехватки опыта - я совсем новичок. Будет уроком. А как отменить зависшие пинги, чтобы приложение быстро закрылось, когда пользователь нажмёт Exit?
Sabre вне форума Ответить с цитированием
Старый 30.01.2017, 16:17   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
waleri на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Асинхронный пинг множества хостов kpoko C# (си шарп) 7 20.03.2013 17:01
Асинхронный поток coNsept C# (си шарп) 1 28.09.2012 10:22
Асинхронный вызов в C# q_proger C# (си шарп) 7 16.12.2010 23:27
Асинхронный просмотр Claster Помощь студентам 6 11.02.2010 15:38
Асинхронный сокет raspberry C/C++ Сетевое программирование 8 07.07.2009 16:51