Как проверить, является ли сетевой адрес локальным в Qt

c++ qt

942 просмотра

1 ответ

Я хочу знать, указывает ли сетевой адрес (имя или IP) на удаленный сервер или локальную машину. Я могу использовать QHostInfoдля поиска IP-адрес, но в этом случае мне придется ждать ответа DNS-сервера. Я не хочу знать IP-адрес сервера, мне нужно только проверить, является ли он локальным или нет. Есть ли более быстрый способ проверить это?

Автор: Алексей Рочев Источник Размещён: 12.11.2019 09:27

Ответы (1)


0 плюса

Решение

Я могу использовать QHostInfoдля поиска IP-адрес, но в этом случае мне придется ждать ответа DNS-сервера.

QHostInfoиспользует платформенный механизм разрешения имен. Он может вообще не использовать DNS. Если имя хоста локального интерфейса находится в файле hosts, и разрешение имени настроено на его использование, то QHostInfoадрес локального интерфейса будет разрешен таким образом. В противном случае он выполнит запрос к серверу имен, если платформа настроена для разрешения имен таким образом.

Максимум, что вы можете сделать, это проверить QHostAddress::isLoopback(), а затем проверить, является ли он одним из QNetworkInterface::allAddresses().

Если ваш адрес не является IP-адресом, и он не равен QHostInfo::localHostName(), то сначала вам нужно получить его QHostInfo::lookupHost. Если это имя локального интерфейса, указанное в файле hosts или аналогичный механизм локального разрешения, оно будет быстро возвращено. Вы можете установить короткий тайм-аут (скажем, 100 мс), и если к тому времени результаты поиска не будут доступны, вы можете предположить, что это не локальный интерфейс.

Вот пример:

// https://github.com/KubaO/stackoverflown/tree/master/questions/host-lookup-36319049
#include <QtWidgets>
#include <QtNetwork>

class IfLookup : public QObject {
   Q_OBJECT
   int m_id;
   QTimer m_timer;
   void abort() {
      if (m_timer.isActive())
         QHostInfo::abortHostLookup(m_id);
      m_timer.stop();
   }
   Q_SLOT void lookupResult(const QHostInfo & host) {
      m_timer.stop();
      if (host.error() != QHostInfo::NoError)
         return hasResult(Error);
      for (auto ifAddr : QNetworkInterface::allAddresses())
         if (host.addresses().contains(ifAddr))
            return hasResult(Local);
      return hasResult(NonLocal);
   }
public:
   enum Result { Local, NonLocal, TimedOut, Error };
   IfLookup(QObject * parent = 0) : QObject(parent) {
      connect(&m_timer, &QTimer::timeout, this, [this]{
         abort();
         emit hasResult(TimedOut);
      });
   }
   Q_SIGNAL void hasResult(Result);
   Q_SLOT void lookup(QString name) {
      abort();
      name = name.trimmed().toUpper();
      QHostAddress addr(name);
      if (!addr.isNull()) {
         if (addr.isLoopback() || QNetworkInterface::allAddresses().contains(addr))
            return hasResult(Local);
         return hasResult(NonLocal);
      }
      if (QHostInfo::localHostName() == name)
         return hasResult(Local);
      m_id = QHostInfo::lookupHost(name, this, SLOT(lookupResult(QHostInfo)));
      m_timer.start(500);
   }
};

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QWidget w;
   QFormLayout layout{&w};
   QLineEdit address;
   layout.addRow("Address to look up", &address);
   QLabel result;
   layout.addRow("Result", &result);
   QPushButton lookup{"Lookup"};
   layout.addRow(&lookup);
   lookup.setDefault(true);
   w.show();

   IfLookup ifLookup;
   QObject::connect(&lookup, &QPushButton::clicked, [&]{
      result.clear();
      ifLookup.lookup(address.text());
   });
   QObject::connect(&ifLookup, &IfLookup::hasResult, [&](IfLookup::Result r){
      static const QMap<IfLookup::Result, QString> msgs = {
         { IfLookup::Local, "Local" }, { IfLookup::NonLocal, "Non-Local" },
         { IfLookup::TimedOut, "Timed Out" }, { IfLookup::Error, "Lookup Error" }
      };
      result.setText(msgs.value(r));
   });

   return app.exec();
}

#include "main.moc"
Автор: Kuba Ober Размещён: 30.03.2016 09:17
Вопросы из категории :
32x32