Qt: Как получить MAC-адрес удаленного ПК (узла связи)?

Я использую Qt5 на Windows 7.
В моем приложении (сервер TCP) в настоящее время я использую некоторые методы из класса QTcpSocket:
- QAbstractSocket::peerAddress() для того, чтобы получить адрес партнера;
- QAbstractSocket::peerPort() для того, чтобы получить одноранговый порт.

Я также хотел бы получить MAC-адрес узла связи.
Возможно ли это без использования специального протокола (т.е. без необходимости обмена некоторыми пользовательскими сообщениями между моим приложением и партнером)? Если да, то как?

2 ответа

Решение

Я также хотел бы получить MAC-адрес узла связи. Возможно ли это без использования специального протокола (т.е. без необходимости обмена некоторыми пользовательскими сообщениями между моим приложением и партнером)? Если да, то как?

В общем, нет, это невозможно, так как узел связи может даже не иметь MAC-адреса (например, если он использует сетевое оборудование, не основанное на Ethernet). В частности, информация о MAC-адресах не передается уровнями IP, TCP или UDP - эти уровни вместо этого используют IP-адреса. Поэтому, если вы хотите узнать MAC-адрес однорангового узла, вам нужно будет сделать это на уровне приложения, если программа на одноранговом узле отправит его вам.

(Одно незначительное исключение из вышеперечисленного: если вы общаетесь через IPv6 и используете самоназначенные локальные IPv6-адреса каналов (например, fe80::blah), можно получить MAC-адрес компьютера из его самоназначенного IPv6-адреса, потому что самоназначенный IPv6-адрес обычно получается из MAC-адреса и содержит MAC-адрес в качестве подмножества своего IPv6-адреса. [Обратите внимание, что это не будет работать через Интернет, так как локальные адреса канала полезны только тогда, когда обе машины расположены на та же ЛВС])

Вот код для получения MAC-адреса узла связи.
Под капотом используется команда Windows arp.
Использование Qt5.8, протестировано на Windows 7:

QString getMacForIP(QString ipAddress)
{
    QString MAC;
    QProcess process;
    //
    process.start(QString("arp -a %1").arg(ipAddress));
    if(process.waitForFinished())
    {
        QString result = process.readAll();
        QStringList list = result.split(QRegularExpression("\\s+"));
        if(list.contains(ipAddress))
            MAC = list.at(list.indexOf(ipAddress) + 1);
    }
    //
    return MAC;
}

Примечание: удаленный узел должен быть в той же локальной сети.
Еще одно замечание: вы получите пустую строку для MAC, если IP-адрес отсутствует.

Если вы можете запустить код на удаленном узле, MAC-адрес можно сообщить с помощью вызова hardwareAddress() интерфейса.

Например, чтобы сообщить MAC-адрес интерфейса WiFi и все адреса IPv4 на этом интерфейсе:

for(const QNetworkInterface& iface: QNetworkInterface::allInterfaces()){
    if (iface.type() == QNetworkInterface::Wifi){
        qDebug() << "MAC:" << iface.hardwareAddress();
        for (const QHostAddress& addr : iface.allAddresses()){
            if (addr.protocol() == QAbstractSocket::IPv4Protocol)
                qDebug() << "IPv4 Addr: " << addr;
        }
    }
}
Другие вопросы по тегам