Blog. Just Blog

Определение состояния подключения к сети на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Определение состояния подключения к сети на Ассемблере
Определение состояния подключения к сети на Ассемблере

Вдогонку к недавней статье. Если вы разрабатываете приложение, которое должно работать с какими-то данными в интернете, всегда будет полезно знать, есть ли у компьютера подключение к сети и разрешен ли приложению выход в сеть. В этих ваших интернетах приводят несколько способов решения задачи, но, как и йогурты из рекламы, не все они одинаково полезны. Давайте разберемся, какие функции стоит использовать на практике, а какие нет.

Первый способ основан на получении количества подключений к удаленному серверу с помощью функции RasEnumConnections. Этот способ работает только с модемным подключением, которое в наше время безнадежно устарело и почти нигде не встречается. При подключении через беспроводную или локальную сеть результат функции всегда будет неправильным. Этот способ можно использовать только для того, чтобы определить факт модемного соединения, но не для определения состояния подключения к сети.
  1.         ; Проверка подключения через RasEnumConnections
  2.         mov     [tmp],0
  3.         mov     [tmp2],0
  4.         invoke  RasEnumConnections,NULL,tmp,tmp2
  5.         cmp     [tmp2],0
  6.         je      no_internet_connection
Второй способ - использование функции InetIsOffline. В теории она должна возвращать TRUE, если в данный момент система не подключена к интернету, и FALSE, если есть соединение или с момента запуска еще не было ни одной попытки это соединение установить. Но это в теории. На практике функция всегда возвращает FALSE, даже если вообще никаких подключений нет. Использовать категорически не рекомендуется.
  1.         ; Проверка подключения через InetIsOffline
  2.         invoke  InetIsOffline,NULL
  3.         cmp     eax,TRUE
  4.         je      no_internet_connection
Третий способ - проверка доступности определенного адреса в сети посредством функции InternetCheckConnection. Очень хороший и надежный способ, тут главное использовать для проверки какой-нибудь надежный адрес, который всегда доступен. Минус этого способа заключается в том, что такие обращения к удаленному ресурсу перехватываются фаерволом и могут быть заблокированы. Ну и гарантировать стопроцентную доступность не может ни один, даже самый надежный сайт.
  1. szUrl   db 'https://yandex.ru',0
  2.         ...
  3.         ...
  4.         ; Проверка подключения через InternetCheckConnection
  5.         FLAG_ICC_FORCE_CONNECTION = 1
  6.         invoke  InternetCheckConnection,szUrl,FLAG_ICC_FORCE_CONNECTION,NULL
  7.         cmp     eax,FALSE
  8.         je      no_internet_connection
Самый правильный способ, чтобы определить состояния подключения к сети, это использование функции InternetGetConnectedState. Ее результат не зависит от прав доступа конкретного приложения, поэтому в совокупности с предыдущей функцией ее можно использовать для определения ситуаций, когда соединение с интернетом есть, но при этом ваше приложение заблокировано на фаерволе. Также по возвращаемому значению можно определить тип соединения, в связи с чем первый способ полностью теряет актуальность.
  1.         ; Проверка подключения через InternetGetConnectedState
  2.         invoke  InternetGetConnectedState,tmp,NULL
  3.         cmp     eax,FALSE
  4.         je      no_internet_connection
Еще один неплохой способ - функция IsNetworkAlive, доступная, начиная с Windows XP.
  1.         ; Проверка подключения через IsNetworkAlive
  2.         invoke  IsNetworkAlive,tmp
  3.         cmp     [tmp],0
  4.         je      no_internet_connection
Любителям COM-интерфейсов понравится следующий метод. На современных системах, начиная с Windows Vista, есть набор функций, объединенных общим названием Network List Manager. Некоторые из них предназначены именно для проверки подключения к сети или проверки возможности выхода в Интернет. Но, как обычно, нам сперва понадобится некоторое количество констант, GUID и структур интерфейса.
  1. ; GUID {DCB00C01-570F-4A9B-8D69-199FDBA5723B}
  2. CLSID_NetworkListManager dd 0DCB00C01h
  3.                          dw 0570Fh
  4.                          dw 04A9Bh
  5.                          db 08Dh, 069h, 019h, 09Fh, 0DBh, 0A5h, 072h, 03Bh
  6.  
  7. ; GUID {DCB00000-570F-4A9B-8D69-199FDBA5723B}
  8. IID_INetworkListManager dd 0DCB00000h
  9.                         dw 0570Fh
  10.                         dw 04A9Bh
  11.                         db 08Dh, 069h, 019h, 09Fh, 0DBh, 0A5h, 072h, 03Bh
  12.  
  13. ; IID_INetworkListManager Interface
  14. struct INetworkListManager
  15.     ; IUnknown
  16.     QueryInterface            dd ?   ; 000h
  17.     AddRef                    dd ?   ; 004h
  18.     Release                   dd ?   ; 008h
  19.     ; INetworkListManager
  20.     GetTypeInfoCount          dd ?   ; 00Ch
  21.     GetTypeInfo               dd ?   ; 010h
  22.     GetIDsOfNames             dd ?   ; 014h
  23.     _Invoke                   dd ?   ; 018h
  24.     GetNetworks               dd ?   ; 01Ch
  25.     GetNetwork                dd ?   ; 020h
  26.     GetNetworkConnections     dd ?   ; 024h
  27.     GetNetworkConnection      dd ?   ; 028h
  28.     get_IsConnectedToInternet dd ?   ; 02Ch
  29.     get_IsConnected           dd ?   ; 030h
  30.     GetConnectivity           dd ?   ; 034h
  31.     SetSimulatedProfileInfo   dd ?   ; 038h
  32.     ClearSimulatedProfileInfo dd ?   ; 03Ch
  33. ends
  34.  
  35. CLSCTX_INPROC_SERVER    = 1
  36. S_OK                    = 0
Теперь сам код. Тут все операции типичные для работы с COM, ничего нового. Создаем объект INetworkListManager, затем через его метод get_IsConnectedToInternet проверяем возможность выхода в Интернет. С помощью похожего метода get_IsConnected определяется наличие сетевого подключения вообще.
  1.         invoke  CoInitialize,NULL
  2.  
  3.         ; Создать объект
  4.         invoke  CoCreateInstance,CLSID_NetworkListManager,NULL,\
  5.                 CLSCTX_INPROC_SERVER,\
  6.                 IID_INetworkListManager,pINLMDisp
  7.  
  8.         ; Получить состояние подключения к Интернету
  9.         mov     eax, [pINLMDisp]
  10.         mov     eax, [eax]
  11.         stdcall dword [eax+INetworkListManager.get_IsConnectedToInternet],\
  12.                 [pINLMDisp],IsConnected
  13.  
  14.         ; Прибраться за собой
  15.         mov     eax, [pINLMDisp]
  16.         mov     eax, [eax]
  17.         stdcall dword [eax+INetworkListManager.Release],[pINLMDisp]
  18.  
  19.         ; Удалить объект
  20.         invoke  CoUninitialize
  21.  
  22.         ; Есть подключение к Интернету?
  23.         cmp     [IsConnected],0xFFFF
  24.         jne     no_internet_connection
В приложении пример программы с исходным текстом, которая проверяет состояние подключения к сети всеми описанными в статье способами.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Check.Internet.Connection.Demo.zip (2,619 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 2336 | Комментариев: 7

Метки: Assembler, сеть
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (03.02.2022 в 16:41):
Пример с COM-интерфейсом добавлен, архив обновлен.
ManHunter (03.02.2022 в 15:34):
ЦитатаMinimum supported client Windows Vista [desktop apps only]
Minimum supported server Windows Server 2008 [desktop apps only]

Надо будет попробовать, спасибо за наводку
Владимир (03.02.2022 в 15:32):
Дмитрий, добрый день, такая функция может быть альтернативой для проверки состояния подключения к сети ?
https://docs.microsoft.com/en-...edtointernet
Спасибо за статью! Всё как обычно на высшем уровне, доходчиво и подробно.
dirbeer (05.08.2019 в 13:28):
NoNaMe, Delphi?
Андрей (03.07.2019 в 00:05):
Воу-воу, диалап на картинке!
ManHunter (13.05.2019 в 15:08):
NoNaMe, не совсем так. Эта функция определяет вообще ВОЗМОЖНОСТЬ подключения компа к сети, то есть наличие сетевой карты, модема, адаптера wifi и всякого подобного железа. Во всех этих случаях результат всегда будет положительный. А вот подключен комп через эти устройства к интернету или нет - это не узнать. Так что увы, не годится.

Добавил еще один способ с IsNetworkAlive.
NoNaMe (13.05.2019 в 14:51):
function IsInternetConnected: Boolean;
begin
   Result := GetSystemMetrics(SM_NETWORK) and 1 > 0;
end;

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0071 сек.) / Память: 4.5 Mb
Наверх