Nano Hash - криптовалюты, майнинг, программирование

Проверьте, подключен ли компьютер Windows к Ethernet через C++

Поэтому я попытался найти несколько разных ответов для этого. Один, который, как я думал, может быть многообещающим, был следующим:

Как проверить сеть тип интерфейса — Ethernet или Wireless в Windows с использованием Qt?

Однако я не слишком много знаю о сетях или даже о Windows. Лично я не могу понять большую часть документации Microsoft на их сайтах. Я пробовал такие вещи, как INetworkConnection, NativeWiFi и т. д. Но либо они не делают то, что я хочу, либо я просто не могу понять, как это сделать из доступной документации.

При этом я хотел бы использовать C++, чтобы проверить, подключено ли устройство, на котором запускается эта программа, к Интернету через кабель Ethernet. В принципе, я хочу сделать следующее:

  • Если компьютер подключен только к беспроводной сети, запустите программу
  • Если компьютер подключен только к Wired, не запускайте программу
  • Если компьютер подключен как к проводной, так и к беспроводной сети, не запускайте программу.

Однако проблема в том, что я не знаю, как проверить, подключено ли устройство к Ethernet. Есть ли способ сделать это? Я НЕ использую QT. Спасибо!


РЕДАКТИРОВАТЬ: я должен также включить то, что я пробовал до сих пор.

Я пытался использовать GetAdaptersInfo и получить черту Type из типа переменной PIP_ADAPTER_INFO, но это всегда дает мне Unknown type 71 независимо от того, подключен я к сети Ethernet или нет.

Документация для этого GetAdaptersInfo находится здесь: https://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx

Спасибо


РЕДАКТИРОВАТЬ 2: вот код, который я использовал для GetAdaptersInfo

bool is_on_ethernet{
    PIP_ADAPTER_INFO pAdapterInfo;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD dwRetVal = 0;
    UINT i;

    struct tm newtime;
    char buffer[32];
    errno_t error;

    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));

    if(pAdapterInfo == NULL)
        printf("Error allocating memory need to call GetAdaptersInfo");

    if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
        free(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
    }

    if((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
        pAdapter = pAdapterInfo;

        switch(pAdapter->Type){
            case MIB_IF_TYPE_OTHER:
                printf("Other\n");
                return false;
                break;
            case MIB_IF_TYPE_ETHERNET:
                printf("Ethernet\h");
                return true;
                break;
            case MIB_IF_TYPE_TOKENRING:
                printf("Token Ring\n");
                return false;
                break;
            case MIB_IF_TYPE_FDDI
                printf("FDDI\n");
                return false;
                break;
            case MIB_IF_TYPE_PPP
                printf("PPP\n");
                return false;
                break;
            case MIB_IF_TYPE_LOOPBACK
                printf("Lookback\n");
                return false;
                break;
            case MIB_IF_TYPE_SLIP
                printf("Slip\n");
                return false;
                break;
            default
                printf("Unknown type %ld\n\n", pAdapter->Type);
                return false;
                break;
        }
    }

    if(pAdapterInfo)
        free(pAdapterInfo);

    return false;
}

  • У вас есть пример кода вашей попытки использовать GetAdaptersInfo? 14.08.2015
  • Я делаю; Я добавлю это как редактирование сейчас. Извините, что не включил это! 14.08.2015
  • @ Nighthawk441 Хорошо - я включил код в качестве редактирования. Еще раз извините за отсутствие кода раньше! Спасибо за комментарий :) 14.08.2015
  • У меня недостаточно информации для ответа. Но насколько мне известно, GetAdaptersInfo вернет связанный список всех установленных адаптеров. Код, который у вас есть, похож на пример кода, найденный в msdn, который проверяет только первый адаптер. Таким образом, вам нужно будет пройти через каждый адаптер, используя указатель Next в IP_ADAPTER_INFO. Вы можете получить каждый тип адаптера, но он не скажет, подключен он или нет. 14.08.2015
  • @Nighthawk441 Nighthawk441 Ах, хорошо, я не понял, что код проверял только первый адаптер. Я буду работать над их циклом, а затем попытаюсь выяснить, подключен ли каждый из них. Спасибо! 14.08.2015
  • @ Nighthawk441 Я не уверен, выходит ли этот вопрос за рамки комментария или нет; Я добавил цикл while(pAdapterInfo->Next){} вокруг оператора switch (после if(...NO_ERROR)), но это, кажется, вызывает бесконечный цикл. Это то, что вы имели в виду, говоря об использовании указателя Next, или я неправильно реализовал ваш комментарий? 14.08.2015
  • Вы, вероятно, ищете while(pAdapterInfo = pAdapterInfo-›Next()), но вам, вероятно, следует посмотреть на это: msdn.microsoft.com/en-us/library/windows/desktop/ в нем есть пример кода почти всех функций IP Helper 14.08.2015
  • Я могу ответить на ваш вопрос, но сначала мне нужно его понять. Что вы имеете в виду под run the program и dont run the program? Какая программа? Как вы собираетесь его начать и почему? Какое отношение сетевой адаптер имеет к программам? Вы уверены, что не можете просто включить все алгоритмы программы в свой? 14.08.2015
  • @specializt Спасибо за интерес к специалисту. Все, что я имею в виду, это то, что у меня есть написанный мной код C++, который работает прямо сейчас; он выполняет ряд функций. Однако я хочу добавить некоторые функции в этот код. Все, что я хочу сделать, это то, что если пользователь только что подключился к беспроводной сети, код продолжит выполнение функций. Однако, если подключен Ethernet, функции никогда не будут выполняться. По сути, я просто хочу добавить if(ethernet is not connected){run functions}else{do not run functions} в мой текущий функциональный код C++. 15.08.2015
  • Приложение @specializt: вот почему я использую логическую функцию - чтобы я мог просто вызвать функцию в желаемом операторе if. Например if(!is_on_ethernet){run rest of code}. Надеюсь, это поможет! Дайте мне знать, если я могу уточнить что-то еще или что-то еще. 15.08.2015
  • это не то, что означает запустить программу .... слова, которые вы искали, возвращают true и возвращают false. 15.08.2015

Ответы:


1

Ваша проблема несколько сложна, так как может быть очень сложно получить «текущий» сетевой адаптер — Windows направляет пакеты в зависимости от конфигурации сетевого адаптера и доступности пункта назначения, поэтому ваш «текущий» адаптер может измениться в любое время ... но поскольку вы уже знаете, как получить IP-адреса и MAC-адреса («аппаратный адрес») доступных адаптеров, вы можете просто использовать свой хак, чтобы получить MAC-адрес для вашего текущего IP-адреса и отфильтровать / найти его внутри моей второй функции! Поле «PhysicalAddress» — это то, что вам нужно, это MAC-адрес.

Я убедился, что единственный надежный способ сделать это — через GetIfTable и GetIfTable2, первый возвращает несколько поверхностная информация об адаптере, а последний предоставляет отличные подробности. Вот пример реализации, поскольку он использует подробную функцию, которую вы также можете запросить для адаптеров WLAN:

vector<MIB_IF_ROW2>* getDevices(NDIS_PHYSICAL_MEDIUM type)
    {       
        vector<MIB_IF_ROW2> *v = new vector<MIB_IF_ROW2>();
        PMIB_IF_TABLE2 table = NULL;
        if(GetIfTable2Ex(MibIfTableRaw, &table) == NOERROR && table)
        {
            UINT32 i = 0;
            for(; i < table->NumEntries; i++)
            {
                MIB_IF_ROW2 row;

                ZeroMemory(&row, sizeof(MIB_IF_ROW2));
                row.InterfaceIndex = i;
                if(GetIfEntry2(&row) == NOERROR)
                {                   
                    if(row.PhysicalMediumType == type)
                    {
                        v->push_back(row);
                    }                   
                }           
            }
            FreeMibTable(table);
        }
        return v;
    }

Теперь все, что вам нужно сделать, это перебрать список и отфильтровать отключенные адаптеры и еще много чего:

vector<MIB_IF_ROW2>* wlan = getDevices(NdisPhysicalMediumNative802_11); //WLAN adapters
//see https://msdn.microsoft.com/en-us/library/windows/desktop/aa814491(v=vs.85).aspx, "PhysicalMediumType" for a full list
for(auto &row : *v)
    {
        //do some additional filtering, this needs to be changed for non-WLAN           
        if( row.TunnelType == TUNNEL_TYPE_NONE &&
            row.AccessType != NET_IF_ACCESS_LOOPBACK &&         
            row.Type == IF_TYPE_IEEE80211 &&
            row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE)              
            {
                //HERE BE DRAGONS!                    
            }
    }

Теперь довольно легко создать списки адаптеров WLAN и адаптеров, не относящихся к WLAN (см. комментарий во второй функции), найти текущий MAC-адрес и сделать вывод, что он проводной или беспроводной, но имейте в виду, что эти списки может перекрываться, поскольку 802.11 в основном является расширенной версией 802.3 но 802.3 не включает 802.11 (поскольку это расширение) - поэтому вам понадобится немного логики if/else, чтобы отделить адаптеры WLAN от адаптеров, не относящихся к WLAN.

Вы также можете использовать WlanEnumInterfaces чтобы получить все адаптеры WLAN, но это в основном то же самое, что и использование вышеуказанной функции с NdisPhysicalMediumNative802_11 в качестве параметра...

15.08.2015
  • Это кажется хорошим ответом, но, к сожалению, я немного смущен. Когда я перебираю вектор, как во втором блоке кода, многие атрибуты строк остаются одинаковыми. Как отличить беспроводную сеть от проводной? Как узнать, подключен ли пользователь к Ethernet? Я пытался использовать атрибуты физического адреса, но они, похоже, не дают мне MAC-адрес, поэтому я не уверен, с чем сравнивать. Извините за путаницу. Спасибо! 17.08.2015
  • Хорошо, после некоторых экспериментов я получил этот ответ на работу. Я изменил оператор if на if(row.Type == IF_TYPE_ETHERNET_CSMACD && row.MediaConnectState == MdiaConnectStateConnected), а затем вернул true внутри этого оператора if. Большое спасибо за ваше время и помощь. Я приму этот ответ сейчас. 18.08.2015
  • ^добавление: я также изменил параметр, который отправлял в функцию getDevices, на NdisPhysicalMedium802_3 18.08.2015

  • 2

    Итак, во-первых, большое спасибо пользователю @Nighthawk441 за то, что указал мне правильное направление для этого. Без этого пользователя я бы точно не придумал решение.

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

    Короче говоря, я перебрал все адаптеры из GetAdaptersInfo. Чтобы увидеть, был ли подключен адаптер, я сравнил IP-адрес адаптера со строкой "0.0.0.0", как если бы это было что-то другое, я чувствовал, что можно с уверенностью сказать, что адаптер подключен. Итак, без лишних слов, вот код, который я реализовал.

    bool is_on_ethernet(){
        PIP_ADAPTER_INFO pAdapterInfo;
        PIP_ADAPTER_INFO pAdapter = NULL;
        DWORD dwRetVal = 0;
        UINT i;
    
        struct tm newtime;
        char buffer[32];
        errno_t error;
    
        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    
        if(pAdapterInfo == NULL)
            printf("Error allocating memory needed to call GetAdaptersInfo");
    
        if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
            free(pAdapterInfo);
            pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
        }
    
        if((dwRetValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
            do{
                pAdapter = pAdapterInfo;
    
                string ip_string = pAdapter->IpAddressList.IpAddress.String;
    
                switch(pAdapter->Type){
                    case MIB_IF_TYPE_OTHER:
                        printf("Other\n");
                        break;
                    ...
                    case MIB_IF_TYPE_ETHERNET:
                        printf("Ethernet\n");
    
                        //new code
                        if(ip_string.compare("0.0.0.0") != 0){
                            free(pAdapterInfo);
                            return true;
                        }
    
                        break;
                    default:
                        printf("Unknown type %ld\n", pAdapter->Type);
                        break;
                }
            }while(pAdapterInfo = pAdapterInfo->Next);
        }
    
        if(pAdapterInfo)
            free(pAdapterInfo);
    
        return false;
    }
    

    Глядя на эту ссылку действительно помог мне:

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa365819%28v=vs.85%29.aspx

    Так что спасибо Nighthawk за предоставленную мне информацию. Надеюсь, это поможет кому-то еще! Если у кого-то есть какие-либо комментарии или любые другие ответы, не стесняйтесь публиковать их! Спасибо!

    14.08.2015
  • Я думал, что это должно быть С++? Этот код полон отвратительного ручного управления памятью. 15.08.2015
  • это попытка новичка ... пока не судите его - вместо этого подробно укажите на недостатки и приведите примеры того, как это делается. 15.08.2015
  • @Puppy Этот код якобы скопирован непосредственно из ссылки MSDN, которую я упомянул в своем ответе. Я добавил в общей сложности еще один[1] оператор free(...). Если проблема с управлением памятью, то мне придется отклониться и сказать, что это проблема с документацией MSDN. 17.08.2015
  • ^когда я сказал ответ, я, конечно, имел в виду свой вопрос. документация находится здесь 17.08.2015
  • MSDN славится ужасными примерами... скорее всего, их постоянно пишут неопытные веб-разработчики. Лучше не копировать/вставлять их, а вместо этого посмотреть на ОСНОВНУЮ функциональность и использовать ее — многие примеры не только полны ошибок, но и иногда представляют собой огромные риски для безопасности. 18.08.2015
  • @specializt Это определенно имеет смысл. Я постараюсь использовать этот подход в будущем. Я просто хочу, чтобы основные функции было легче определить из скудной документации, представленной на этом веб-сайте. 18.08.2015

  • 3

    Основываясь на ответе @specializt и с некоторыми незначительными изменениями, у меня это получилось следующим образом:

    BOOL getDevices(NDIS_PHYSICAL_MEDIUM type, vector<MIB_IF_ROW2>& vetIFRow)
    {
        PMIB_IF_TABLE2 table = NULL;
        if (GetIfTable2Ex(MibIfTableRaw, &table) != NOERROR || !table)
        {
            return FALSE;
        }
    
        for (ULONG i = 0; i < table->NumEntries; i++)
        {
            MIB_IF_ROW2 row;
            ZeroMemory(&row, sizeof(MIB_IF_ROW2));
            row.InterfaceIndex = i;
            if (GetIfEntry2(&row) == NOERROR && row.PhysicalMediumType == type)
            {
                vetIFRow.push_back(row);
            }
        }
    
        FreeMibTable(table);
        return TRUE;
    }
    
    BOOL isNetIFConnected(const MIB_IF_ROW2& row, IFTYPE Type)
    {
        return (row.TunnelType == TUNNEL_TYPE_NONE &&
            row.AccessType != NET_IF_ACCESS_LOOPBACK &&
            row.Type == Type &&
            row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE &&
            row.MediaConnectState == MediaConnectStateConnected);
    }
    
    tstring getNetWorkType()
    {
        vector<MIB_IF_ROW2> vectRow;
        BOOL bRet = getDevices(NdisPhysicalMedium802_3, vectRow); // ETHERNET adapters
        if (bRet)
        {
            for (auto it = vectRow.begin(); it != vectRow.end(); it++)
            {
                if (isNetIFConnected(*it, IF_TYPE_ETHERNET_CSMACD))
                {
                    return L"ETHERNET";
                }
            }
        }
    
        vectRow.clear();
        bRet = getDevices(NdisPhysicalMediumNative802_11, vectRow); //WLAN adapters
        if (bRet)
        {
            for (auto it = vectRow.begin(); it != vectRow.end(); it++)
            {
                if (isNetIFConnected(*it, IF_TYPE_IEEE80211))
                {
                    return L"WIFI";
                }
            }
        }
    
        return L"Unknown";
    }
    

    Спасибо @specializt

    06.06.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..