How to check if network address is local in Qt

后端 未结 1 915
滥情空心
滥情空心 2021-01-25 21:07

I want to know if network address (name or IP) points to remote server or local machine. I can use QHostInfo to lookup IP address, but in this case I would have to

相关标签:
1条回答
  • 2021-01-25 21:45

    I can use QHostInfo to lookup IP address, but in this case I would have to wait for DNS server's response.

    QHostInfo uses the platform-specific name resolution mechanism. It might not use DNS at all. If the hostname of a local interface is in the hosts file, and the name resolution is configured to use it, then QHostInfo will resolve the local interface's address that way. Otherwise, it'll do a name server query, iff the platform is configured to resolve names that way.

    The most you can do is to check QHostAddress::isLoopback(), then check if it's one of QNetworkInterface::allAddresses().

    If your address is not an IP address, and it's not equal to QHostInfo::localHostName(), then you have to obtain one first using QHostInfo::lookupHost. If it's a local interface's name, listed in the hosts file or a similar local resolution mechanism, it will be returned quickly. You can set a short timeout (say 100ms), and if there's no lookup result available by then, you can assume that it's not a local interface.

    Here's an example:

    // 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"
    
    0 讨论(0)
提交回复
热议问题