简体   繁体   中英

convert ip address to a single number

I have a file which contains more than 100 ip addresses(dotted decimal.eg. 169.23.43.12). Now I need to read all the ip addresses and sort in ascending order. For this, first of all I tried to convert all the ip addresses into its equivalent integer number.I created a c++ function to convert the ip addresses, but it did not work for large ip address, such as 255.250.120.100. I tried to use inet_aton() and inet_ntoa(). But using these two, I could not sort the ip addresses. So, please give me an idea to convert the ip addresses into a form which could be sorted. Below are some codes by using which I tried to sort ip address, but did not work.

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

You can do this with a custom comparator for struct sokaddr_in. The snippet below explains what I mean. The advantage of this approach is you can customize the comparator for IPv6 and to include port nos. and other stuff if IP addresses are same.

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

Hope this helps.

Solution for converting a string formatted IPv4 address to an unsigned integer using std::istringstream .

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

Example results

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

Convert the addresses to unsigned integers. The code could look like this:

//  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];

Insert all identifiers to some vector/array and sort it.

The third inet_pton parameter is a pointer to an in_addr structure.
After a successful inet_pton call, the in_addr structure will be populated with the address information. The structure's S_addr field contains the IP address in network byte order (reverse order). The ntohl function will convert the address from network byte order to host byte order.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM