将IP地址转换为一个单一的数字

3
我有一个文件,其中包含100多个IP地址(点分十进制格式,例如169.23.43.12)。现在我需要读取所有IP地址并按升序排序。为此,首先我尝试将所有IP地址转换为其等效的整数。我创建了一个C ++函数来转换IP地址,但对于大型IP地址(例如255.250.120.100),它无法正常工作。我尝试使用inet_aton()和inet_ntoa(),但是使用这两个函数,我无法对IP地址进行排序。因此,请给我一个将IP地址转换为可排序形式的想法。以下是一些代码,我尝试使用它们来对IP地址进行排序,但未能成功。
结构体sockaddr_in antelope [2]; char *some_addr;
inet_aton("60.0.0.4", &antelope[0].sin_addr); // store IP in antelope
inet_aton("10.0.0.2", &antelope[1].sin_addr); // store IP in antelope
std::sort(antelope,antelope+2);
cout<<inet_ntoa(antelope[0].sin_addr)<<endl;
cout<<inet_ntoa(antelope[1].sin_addr)<<endl;

什么没有起作用?出现了什么错误?std::sort不知道如何对sockaddr_in结构进行排序。 - undefined
std::sort出现了一些错误。那么,在使用inet_aton()之后,我该如何对它们进行排序呢?你知道有什么方法可以对它们进行排序吗? - undefined
你使用了无符号整数吗?如果你使用了有符号整数,可能会出现你所遇到的行为。 - undefined
我在自己的函数中使用了无符号整数来将IP地址转换为整数。对于像10.10.127.12这样的小型IP地址,它运行得非常完美。当我在32位操作系统的机器上输入一个像255.234.100.3这样的IP地址时,它给出了准确的结果。但是在64位操作系统的机器上,它给出了非常大的数字。 - undefined
4个回答

5
你可以使用自定义比较器来处理结构体sokaddr_in。下面的代码片段解释了我的意思。这种方法的优点是,如果IP地址相同,你可以根据需要为IPv6和端口号等其他内容定制比较器。
    #include <iostream>
    #include <algorithm>
    #include <arpa/inet.h>


    struct CompareSockAddr_in
    {
        bool operator ()(struct sockaddr_in ip1,struct sockaddr_in ip2){
            // use return ip1.sin_addr.s_addr < ip2.sin_addr.s_addr; for ascending order
return ip1.sin_addr.s_addr > ip2.sin_addr.s_addr;
        }
    };

    int main()
    {
        struct sockaddr_in antelope[2];

        inet_pton(AF_INET, "10.0.0.2", &(antelope[0].sin_addr));
        inet_pton(AF_INET, "60.0.0.4", &(antelope[1].sin_addr));

        std::cout<<inet_ntoa(antelope[0].sin_addr)<<std::endl;
        std::cout<<inet_ntoa(antelope[1].sin_addr)<<std::endl;
        std::sort(antelope,antelope+2,CompareSockAddr_in());

        std::cout<<"Sorted List...\n";

        std::cout<<inet_ntoa(antelope[0].sin_addr)<<std::endl;
        std::cout<<inet_ntoa(antelope[1].sin_addr)<<std::endl;

        return 0;
    }

希望这有帮助。

2

使用 std::istringstream 将格式化的 IPv4 地址字符串转换为无符号整数的解决方案。

#include <sstream>

uint32_t convert( const std::string& ipv4Str )
{
    std::istringstream iss( ipv4Str );
    
    uint32_t ipv4 = 0;
    
    for( uint32_t i = 0; i < 4; ++i ) {
        uint32_t part;
        iss >> part;
        if ( iss.fail() || part > 255 ) {
            throw std::runtime_error( "Invalid IP address - Expected [0, 255]" );
        }
        
        // LSHIFT and OR all parts together with the first part as the MSB
        ipv4 |= part << ( 8 * ( 3 - i ) );

        // Check for delimiter except on last iteration
        if ( i != 3 ) {
            char delimiter;
            iss >> delimiter;
            if ( iss.fail() || delimiter != '.' ) {
                throw std::runtime_error( "Invalid IP address - Expected '.' delimiter" );
            }
        }
    }
    
    return ipv4;
}

示例结果

"0.0.0.5"         =>          5
"192.168.0.5"     => 3232235525
"255.250.120.100" => 4294604900
"255.255.255.255" => 4294967295

1

将地址转换为无符号整数。代码可以如下所示:

//  If ip is 132.152.25.103, then unsigned int IP = {132, 152, 25, 103};
unsigned int identifier = 0;
identifier = ((IP[0]*255 + IP[1])*255 + IP[2])*255 + IP[3];

将所有标识符插入到一个向量/数组中并进行排序。

4
256,不是255。最好是左移(<<8),而不是乘法。 - undefined

0
第三个inet_pton参数是指向in_addr结构的指针。
成功调用inet_pton后,in_addr结构将被填充地址信息。 该结构的S_addr字段以网络字节顺序(反向顺序)包含IP地址。 ntohl函数将把地址从网络字节顺序转换为主机字节顺序。
Example : 

#include <arpa/inet.h>
uint32_t NodeIpAddress::getIPv4AddressInteger(std::string IPv4Address) {
    int result;
    uint32_t IPv4Identifier = 0;
    struct in_addr addr;
    // store this IP address in sa:
    result = inet_pton(AF_INET, IPv4Address.c_str(), &(addr));
    if (result == -1) {         
gpLogFile->Write(LOGPREFIX, LogFile::LOGLEVEL_ERROR, _T("Failed to convert IP %hs to IPv4 Address. Due to invalid family of %d. WSA Error of %d"), IPv4Address.c_str(), AF_INET, result);
    }
    else if (result == 0) {
        gpLogFile->Write(LOGPREFIX, LogFile::LOGLEVEL_ERROR, _T("Failed to convert IP %hs to IPv4"), IPv4Address.c_str());
    }
    else {
        IPv4Identifier = ntohl(*((uint32_t *)&(addr)));
    }
    return IPv4Identifier;
}

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