首页 > 解决方案 > parsing the ip/mac adrs from a QStringList

问题描述

I'm trying to parse and show the MAC addresses of my machine for a license program I'm making, but show only those with a valid IP address. I already got the IPs/MACs but I'm unable to see which one is valid and which one is not.

Here's my code:

void FormSerial::PopCB(QStringList CB){
for (int i = 0; i<CB.size(); i++){
  if(CB.at(i) == "0.0.0.0"){
      Log("verdadero " + CB.at(i+1));
      widget.Mac_ComboBox->addItem(CB.at(i+1));
   }else{
      Log("Falso " + CB.at(i));
   }
 }
}

If I do it this way, it shows me those who have no valid IP address, but I want only those with a valid IP. If I change the == to != inside the if, I get nothing.

I have the data like this:

CB = "0.0.0.0", "42:45:65:25:89:45", "196.568.68.49", "45:98:75:85:15:85"

Any idea?

标签: c++qstringlist

解决方案


Try this instead:

void FormSerial::PopCB(const QStringList &CB){
    for (int i = 0; i < CB.size(); i += 2){
        if (CB.at(i) != "0.0.0.0"){
            const QString &mac = CB.at(i+1);
            Log("verdadero " + mac);
            widget.Mac_ComboBox->addItem(mac);
        }
    }
}

Just be aware that this code only handles IPv4 IP address, but machines can have IPv6 IPs as well. So you may need to update the loop to handle that as well, eg:

if (ip != "0.0.0.0" && ip != "0000:0000:0000:0000:0000:0000:0000:0000"){

Note that IPv6 IPs are much harder to parse than IPv4, as they have many different possible representations, so you are better off using an API/library that knows how to parse IP address strings, such as inet_pton() or getaddrinfo(), eg:

bool isValidIPv4(const QString &ip)
{
    in_addr addr;
    return (inet_pton(AF_INET, ip.c_str(), &addr) == 1)
            && (addr.s_addr != 0);
}

bool isValidIPv6(const QString &ip)
{
    static unsigned char in6_any[16] = {};
    in6_addr addr;
    return (inet_pton(AF_INET6, ip.c_str(), &addr) == 1)
            && (memcmp(addr.s6_addr, in6_any, sizeof(in6_any)) != 0);
}

void FormSerial::PopCB(const QStringList &CB){

    for (int i = 0; i < CB.size(); i += 2){
        const QString &ip = CB.at(i);
        if (IsValidIPv4(ip) || IsValidIPv6(ip)){
            const QString &mac = CB.at(i+1);
            Log("verdadero " + mac);
            widget.Mac_ComboBox->addItem(mac);
        }
    }
}
bool IsValidIPv4(const sockaddr *addr)
{
    return (addr->sa_family == AF_INET)
            && (reinterpret_cast<sockaddr_in*>(addr)->sin_addr.s_addr != 0);
}

bool IsValidIPv6(const sockaddr *addr)
{
    static unsigned char in6_any[16] = {};
    return (addr->sa_family == AF_INET6)
            && (memcmp(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr.s6_addr, in6_any, sizeof(in6_any)) != 0);
}

void FormSerial::PopCB(const QStringList &CB){

    addrinfo hints = {}, *res;

    hints.ai_flags = AI_NUMERICHOST;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
           
    for (int i = 0; i < CB.size(); i += 2){
        if (getaddrinfo(CB.at(i).c_str(), NULL, &hints, &res) == 0){
            if (IsValidIPv4(res->ai_addr) || IsValidIPv6(res->ai_addr)){
                const QString &mac = CB.at(i+1);
                Log("verdadero " + mac);
                widget.Mac_ComboBox->addItem(mac);
            }
            freeaddrinfo(res);
        }
    }
}

推荐阅读