QNetworkInterface returns 重复地址

QNetworkInterface returns duplicate addresses

RPi3 的 Qt5.9.2。 这里是当前的目标场景:

# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.167  netmask 255.255.0.0  broadcast 192.168.255.255
        inet6 fd00::b465:a62:a349:a7a5  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::dbfe:16c3:a5cd:9509  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:22:00:43  txqueuelen 1000  (Ethernet)
        RX packets 338  bytes 44737 (43.6 KiB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 238  bytes 27565 (26.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 40  bytes 8560 (8.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 40  bytes 8560 (8.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.179  netmask 255.255.0.0  broadcast 192.168.255.255
        inet6 fd00::2eed:5f16:9646:fe07  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::c460:6252:ee34:8695  prefixlen 64  scopeid 0x20<link>
        ether 00:c6:b1:8f:a1:38  txqueuelen 1000  (Ethernet)
        RX packets 149  bytes 45709 (44.6 KiB)
        RX errors 0  dropped 97  overruns 0  frame 0
        TX packets 106  bytes 17632 (17.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

这是我应该检索 IPv4 地址的代码:

const QHostAddress &localhost = QHostAddress(QHostAddress::LocalHost);
for (const QNetworkInterface &interface: QNetworkInterface::allInterfaces())
{
    QString name = interface.name();
    for (const QHostAddress &address: interface.allAddresses())
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && address != localhost && (interface.flags() & QNetworkInterface::IsRunning))
            qDebug() << name << address << interface.flags();
    }
}

此处输出:

"lo" QHostAddress("192.168.1.167") QFlags(0x1|0x2|0x8)
"lo" QHostAddress("192.168.1.179") QFlags(0x1|0x2|0x8)
"eth0" QHostAddress("192.168.1.167") QFlags(0x1|0x2|0x4|0x20)
"eth0" QHostAddress("192.168.1.179") QFlags(0x1|0x2|0x4|0x20)
"wlan0" QHostAddress("192.168.1.167") QFlags(0x1|0x2|0x4|0x20)
"wlan0" QHostAddress("192.168.1.179") QFlags(0x1|0x2|0x4|0x20)

相反,根据 ifconfig,我预计只有:

"eth0" QHostAddress("192.168.1.167") QFlags(0x1|0x2|0x4|0x20)
"wlan0" QHostAddress("192.168.1.179") QFlags(0x1|0x2|0x4|0x20)

我的代码有误吗?

原因

正如 QNetworkInterface::allInterfaces 的文档所说:

This convenience function returns all IP addresses found on the host machine.

注:重点是我的。

这意味着,对于两个接口,您的代码实质上将遍历地址两次。

解决方案

使用QNetworkInterface::addressEntries instead. Then use QNetworkAddressEntry::ip获取您需要的信息。

例子

下面是建议解决方案的示例实现:

for (auto interface : QNetworkInterface::allInterfaces()) {
    for (auto address : interface.addressEntries()) {
        const QHostAddress &ip(address.ip());

        if (!ip.isLoopback() && (ip.protocol() == QAbstractSocket::IPv4Protocol) && (interface.flags() & QNetworkInterface::IsRunning))
            qDebug() << interface.humanReadableName() << ip.toString();
    }
}