6

I am trying to get the local ip address (IPV4) of a computer in QT. I found the following code:

QNetworkInterface *inter = new QNetworkInterface();
QList<QHostAddress> list;
list=inter->allAddresses();
QString str;

for (int i = 0; i < list.size(); ++i) {
     str = list.at(i).toString();
}

Going through for loop I can see there are a number of values (ip's) in the list, one of them is the actual local ip address that I get by typing ipconfig in a command window.

My question is how to distinguish the ip address from all the ip's that are in list?

TJ1
  • 7,578
  • 19
  • 76
  • 119
  • Filter the interfaces returned by [`allInterfaces()`](http://doc.qt.digia.com/4.7-snapshot/qnetworkinterface.html#allInterfaces) using a couple of [these flags](http://doc.qt.digia.com/4.7-snapshot/qnetworkinterface.html#InterfaceFlag-enum). – Blender Oct 17 '12 at 04:48
  • Computers can have multiple Ethernet interfaces (and often do, say wifi and wired), so they can have more than one IP address. You need to narrow down what you mean by "the local IP" of the computer. – PherricOxide Oct 17 '12 at 04:49
  • Let's say I want the wireless LAN adapter IPV4 address, then one that ipconfig in command line, – TJ1 Oct 17 '12 at 04:53

2 Answers2

13

PCs often have more than one IP address. There's not really such a thing as "the" local IP address; the IP address which would be used when connecting to some remote host depends at least on the local routing table (which may change drastically at any time, e.g. when starting/stopping VPN software).

It seems to me that it makes more sense to think about IPs as valid only in the context of remote networks, e.g. "this is the local IP address I'd use if I were to connect to this host on the Internet; but this is the local IP address I'd use to connect to this host over my company's VPN".

If you want to find out the local IP address which would be used for general-purpose Internet connectivity, the most accurate way I know is simply to do a connection test to a representative host (and a host with high reliability!)

QTcpSocket socket;
socket.connectToHost("8.8.8.8", 53); // google DNS, or something else reliable
if (socket.waitForConnected()) {
    qDebug()
        << "local IPv4 address for Internet connectivity is"
        << socket.localAddress();
} else {
    qWarning()
        << "could not determine local IPv4 address:"
        << socket.errorString();
}

Note: the above example is blocking, you probably want to rewrite it to use signals and slots if your app has a UI.

rohanpm
  • 4,264
  • 17
  • 16
  • 1
    That's a good way of doing it, however, what happens if a PC is is connected to a router (the ip is assigned to the PC by router) but router is not connected to the Internet? For example if one has just a LAN? – TJ1 Oct 17 '12 at 06:07
  • Then this method will correctly determine that there is no local IP address useful for Internet connectivity; in that case, you can replace ("8.8.8.8", 53) with some host you _can_ connect to instead. If you don't know of such a host, I'd say a reasonable default would be whatever primary DNS server is configured (usually sent by the router in a DHCP response). But I don't know how to get that info using Qt :( – rohanpm Oct 17 '12 at 06:16
  • Thanks, I'll wait a while if there is no complete answer I will accept yours ;-) – TJ1 Oct 17 '12 at 06:34
  • DNS runs on UDP not TCP – frogatto Jun 09 '15 at 10:28
  • @frogatto Google DNS servers listen for TCP connections on port 53 as well, so the above does work – TSG Aug 18 '22 at 18:23
2

I think, several attempts should be tried for increasing the chance of the GUESS (Regardless how clever the software is, it would be still a guess, which won't cover 1% of configurations which will be possibly you case :-)

I've combined and extended both solutions. First I'd check for google DNS, and then for local IPs having a standard gateway. The assumption is: Getaway has the same mask with the addreess ending with ".1". I couldn't find out, how to obtain std. gateway in Qt (which would be more reliable).

Here is the code which works ON MY COMPUTERS:

    QTcpSocket dnsTestSocket;   
    QString localIP="127.0.0.1";    //fall back
    QString googleDns = "8.8.8.83";  //try google DNS or sth. else reliable first
    dnsTestSocket.connectToHost(googleDns, 53);
    if (dnsTestSocket.waitForConnected(3000)) 
    {
        localIP = dnsTestSocket.localAddress().toString();
    } 
    else 
    {
        foreach (const QHostAddress &address, QNetworkInterface::allAddresses())
        {
            QString guessedGatewayAddress = address.toString().section( ".",0,2 ) + ".1";

            if (address.protocol() == QAbstractSocket::IPv4Protocol 
                && address != QHostAddress(QHostAddress::LocalHost)
                )
            {
                dnsTestSocket.connectToHost(guessedGatewayAddress, 53);
                if (dnsTestSocket.waitForConnected(3000))
                {
                    localIP = dnsTestSocket.localAddress().toString();
                    break;
                }
            }   
        }
    }
Valentin H
  • 7,240
  • 12
  • 61
  • 111