如何使用QT获取计算机的本地IP地址

6

我正在尝试在QT中获取计算机的本地IP地址(IPV4)。 我找到了以下代码:

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();
}

通过for循环,我可以看到list中有许多值(即IP地址),其中一个是通过在命令窗口中键入ipconfig获取的实际本地IP地址。

我的问题是如何从所有在list中的IP地址中区分出这个IP地址?


使用一些这些标志,过滤allInterfaces()返回的接口。 - Blender
计算机可以拥有多个以太网接口(通常包括无线和有线),因此它们可以拥有多个IP地址。您需要缩小“本地IP”的含义范围。 - PherricOxide
假设我想要获取无线局域网适配器的IPv4地址,那么可以在命令行中使用ipconfig命令来查看。 - TJ1
2个回答

13

通常,个人电脑会拥有多个IP地址。事实上,并不存在所谓的“本地”IP地址;连接到某个远程主机时使用的IP地址至少取决于本地路由表(例如在启动/停止VPN软件时可能会发生巨大变化)。

在我看来,更有意义的做法是将IP地址仅视为远程网络中有效,例如,“如果我要连接到互联网上的这个主机,我将使用此本地IP地址;但如果我要通过公司的VPN连接到这个主机,则将使用另一个本地IP地址。”

如果您想查找用于一般互联网连接的本地IP地址,则我知道的最准确的方法是对具有代表性和高可靠性的主机进行连接测试。

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();
}

注意:上面的示例是阻塞的,如果您的应用程序具有用户界面,您可能希望重写它以使用信号和槽。


1
这是一个不错的做法,但是如果一台电脑连接到路由器(IP由路由器分配),但路由器没有连接到互联网会怎样呢?例如,如果只有一个局域网。 - TJ1
然后,该方法将正确确定没有可用于Internet连接的本地IP地址;在这种情况下,您可以将(“8.8.8.8”,53)替换为您可以连接的某个主机。如果您不知道这样的主机,我会说一个合理的默认值是配置的任何主DNS服务器(通常由DHCP响应中的路由器发送)。但是我不知道如何使用Qt获取该信息:( - rohanpm
谢谢,我会等一段时间,如果没有完整的答案,我会接受你的答案;-) - TJ1
DNS 运行在 UDP 而非 TCP 上。 - frogatto
@frogatto 谷歌 DNS 服务器同样在 53 端口上监听 TCP 连接,所以上述方法是有效的。 - TSG

2

我认为应该尝试几种方法来增加猜测的机会(无论软件多聪明,它仍然只是一个猜测,不可能涵盖1%的配置,也许你的情况就在这1%之中)。

我结合并扩展了两种解决方案。首先,我会检查谷歌DNS,然后检查本地IP是否有标准网关。假设是:网关与以".1"结尾的地址具有相同的掩码。我找不到如何在Qt中获取std.网关(这将更可靠)。

以下是可以在我的电脑上运行的代码:

    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;
                }
            }   
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接