[c++] Get the IP Address of local computer

In C++, what's the easiest way to get the local computer's IP address and subnet mask?

I want to be able to detect the local machine's IP address in my local network. In my particular case, I have a network with a subnet mask of 255.255.255.0 and my computer's IP address is 192.168.0.5. I need to get these had two values programmatically in order to send a broadcast message to my network (in the form 192.168.0.255, for my particular case)

Edit: Many answers were not giving the results I expected because I had two different network IP's. Torial's code did the trick (it gave me both IP addresses). Thanks.

Edit 2: Thanks to Brian R. Bondy for the info about the subnet mask.

This question is related to c++ sockets networking

The answer is


You can use gethostname followed by gethostbyname to get your local interface internal IP.

This returned IP may be different from your external IP though. To get your external IP you would have to communicate with an external server that will tell you what your external IP is. Because the external IP is not yours but it is your routers.

//Example: b1 == 192, b2 == 168, b3 == 0, b4 == 100
struct IPv4
{
    unsigned char b1, b2, b3, b4;
};

bool getMyIP(IPv4 & myIP)
{
    char szBuffer[1024];

    #ifdef WIN32
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(2, 0);
    if(::WSAStartup(wVersionRequested, &wsaData) != 0)
        return false;
    #endif


    if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
    {
      #ifdef WIN32
      WSACleanup();
      #endif
      return false;
    }

    struct hostent *host = gethostbyname(szBuffer);
    if(host == NULL)
    {
      #ifdef WIN32
      WSACleanup();
      #endif
      return false;
    }

    //Obtain the computer's IP
    myIP.b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
    myIP.b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
    myIP.b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
    myIP.b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;

    #ifdef WIN32
    WSACleanup();
    #endif
    return true;
}

You can also always just use 127.0.0.1 which represents the local machine always.

Subnet mask in Windows:

You can get the subnet mask (and gateway and other info) by querying subkeys of this registry entry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces

Look for the registry value SubnetMask.

Other methods to get interface information in Windows:

You could also retrieve the information you're looking for by using: WSAIoctl with this option: SIO_GET_INTERFACE_LIST


How to Obtain the IP Address of the Local Machine on the Network seems to describe the solution quite well...


Also, note that "the local IP" might not be a particularly unique thing. If you are on several physical networks (wired+wireless+bluetooth, for example, or a server with lots of Ethernet cards, etc.), or have TAP/TUN interfaces setup, your machine can easily have a whole host of interfaces.


The question is trickier than it appears, because in many cases there isn't "an IP address for the local computer" so much as a number of different IP addresses. For example, the Mac I'm typing on right now (which is a pretty basic, standard Mac setup) has the following IP addresses associated with it:

fe80::1%lo0  
127.0.0.1 
::1 
fe80::21f:5bff:fe3f:1b36%en1 
10.0.0.138 
172.16.175.1
192.168.27.1

... and it's not just a matter of figuring out which of the above is "the real IP address", either... they are all "real" and useful; some more useful than others depending on what you are going to use the addresses for.

In my experience often the best way to get "an IP address" for your local computer is not to query the local computer at all, but rather to ask the computer your program is talking to what it sees your computer's IP address as. e.g. if you are writing a client program, send a message to the server asking the server to send back as data the IP address that your request came from. That way you will know what the relevant IP address is, given the context of the computer you are communicating with.

That said, that trick may not be appropriate for some purposes (e.g. when you're not communicating with a particular computer) so sometimes you just need to gather the list of all the IP addresses associated with your machine. The best way to do that under Unix/Mac (AFAIK) is by calling getifaddrs() and iterating over the results. Under Windows, try GetAdaptersAddresses() to get similar functionality. For example usages of both, see the GetNetworkInterfaceInfos() function in this file.


from torial: If you use winsock, here's a way: http://tangentsoft.net/wskfaq/examples/ipaddr.html

As for the subnet portion of the question; there is not platform agnostic way to retrieve the subnet mask as the POSIX socket API (which all modern operating systems implement) does not specify this. So you will have to use whatever method is available on the platform you are using.


Also, note that "the local IP" might not be a particularly unique thing. If you are on several physical networks (wired+wireless+bluetooth, for example, or a server with lots of Ethernet cards, etc.), or have TAP/TUN interfaces setup, your machine can easily have a whole host of interfaces.


In DEV C++, I used pure C with WIN32, with this given piece of code:

case IDC_IP:

             gethostname(szHostName, 255);
             host_entry=gethostbyname(szHostName);
             szLocalIP = inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
             //WSACleanup(); 
             writeInTextBox("\n");
             writeInTextBox("IP: "); 
             writeInTextBox(szLocalIP);
             break;

When I click the button 'show ip', it works. But on the second time, the program quits (without warning or error). When I do:

//WSACleanup(); 

The program does not quit, even clicking the same button multiple times with fastest speed. So WSACleanup() may not work well with Dev-C++..


I was able to do it using DNS service under VS2013 with the following code:

#include <Windns.h>

WSADATA wsa_Data;

int wsa_ReturnCode = WSAStartup(0x101, &wsa_Data);

gethostname(hostName, 256);
PDNS_RECORD pDnsRecord;

DNS_STATUS statsus = DnsQuery(hostName, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsRecord, NULL);
IN_ADDR ipaddr;
ipaddr.S_un.S_addr = (pDnsRecord->Data.A.IpAddress);
printf("The IP address of the host %s is %s \n", hostName, inet_ntoa(ipaddr));

DnsRecordListFree(&pDnsRecord, DnsFreeRecordList);

I had to add Dnsapi.lib as addictional dependency in linker option.

Reference here.


You cannot do that in Standard C++.

I'm posting this because it is the only correct answer. Your question asks how to do it in C++. Well, you can't do it in C++. You can do it in Windows, POSIX, Linux, Android, but all those are OS-specific solutions and not part of the language standard.

Standard C++ does not have a networking layer at all.

I assume you have this wrong assumption that C++ Standard defines the same scope of features as other language standards, Java. While Java might have built-in networking (and even a GUI framework) in the language's own standard library, C++ does not.

While there are third-party APIs and libraries which can be used by a C++ program, this is in no way the same as saying that you can do it in C++.

Here is an example to clarify what I mean. You can open a file in C++ because it has an fstream class as part of its standard library. This is not the same thing as using CreateFile(), which is a Windows-specific function and available only for WINAPI.


Can't you just send to INADDR_BROADCAST? Admittedly, that'll send on all interfaces - but that's rarely a problem.

Otherwise, ioctl and SIOCGIFBRDADDR should get you the address on *nix, and WSAioctl and SIO_GET_BROADCAST_ADDRESS on win32.


The problem with all the approaches based on gethostbyname is that you will not get all IP addresses assigned to a particular machine. Servers usually have more than one adapter.

Here is an example of how you can iterate through all Ipv4 and Ipv6 addresses on the host machine:

void ListIpAddresses(IpAddresses& ipAddrs)
{
  IP_ADAPTER_ADDRESSES* adapter_addresses(NULL);
  IP_ADAPTER_ADDRESSES* adapter(NULL);

  // Start with a 16 KB buffer and resize if needed -
  // multiple attempts in case interfaces change while
  // we are in the middle of querying them.
  DWORD adapter_addresses_buffer_size = 16 * KB;
  for (int attempts = 0; attempts != 3; ++attempts)
  {
    adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addresses_buffer_size);
    assert(adapter_addresses);

    DWORD error = ::GetAdaptersAddresses(
      AF_UNSPEC, 
      GAA_FLAG_SKIP_ANYCAST | 
        GAA_FLAG_SKIP_MULTICAST | 
        GAA_FLAG_SKIP_DNS_SERVER |
        GAA_FLAG_SKIP_FRIENDLY_NAME, 
      NULL, 
      adapter_addresses,
      &adapter_addresses_buffer_size);

    if (ERROR_SUCCESS == error)
    {
      // We're done here, people!
      break;
    }
    else if (ERROR_BUFFER_OVERFLOW == error)
    {
      // Try again with the new size
      free(adapter_addresses);
      adapter_addresses = NULL;

      continue;
    }
    else
    {
      // Unexpected error code - log and throw
      free(adapter_addresses);
      adapter_addresses = NULL;

      // @todo
      LOG_AND_THROW_HERE();
    }
  }

  // Iterate through all of the adapters
  for (adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next)
  {
    // Skip loopback adapters
    if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
    {
      continue;
    }

    // Parse all IPv4 and IPv6 addresses
    for (
      IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; 
      NULL != address;
      address = address->Next)
    {
      auto family = address->Address.lpSockaddr->sa_family;
      if (AF_INET == family)
      {
        // IPv4
        SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);

        char str_buffer[INET_ADDRSTRLEN] = {0};
        inet_ntop(AF_INET, &(ipv4->sin_addr), str_buffer, INET_ADDRSTRLEN);
        ipAddrs.mIpv4.push_back(str_buffer);
      }
      else if (AF_INET6 == family)
      {
        // IPv6
        SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);

        char str_buffer[INET6_ADDRSTRLEN] = {0};
        inet_ntop(AF_INET6, &(ipv6->sin6_addr), str_buffer, INET6_ADDRSTRLEN);

        std::string ipv6_str(str_buffer);

        // Detect and skip non-external addresses
        bool is_link_local(false);
        bool is_special_use(false);

        if (0 == ipv6_str.find("fe"))
        {
          char c = ipv6_str[2];
          if (c == '8' || c == '9' || c == 'a' || c == 'b')
          {
            is_link_local = true;
          }
        }
        else if (0 == ipv6_str.find("2001:0:"))
        {
          is_special_use = true;
        }

        if (! (is_link_local || is_special_use))
        {
          ipAddrs.mIpv6.push_back(ipv6_str);
        }
      }
      else
      {
        // Skip all other types of addresses
        continue;
      }
    }
  }

  // Cleanup
  free(adapter_addresses);
  adapter_addresses = NULL;

  // Cheers!
}

I suggest my code.

DllExport void get_local_ips(boost::container::vector<wstring>& ips)
{
   IP_ADAPTER_ADDRESSES*       adapters  = NULL;
   IP_ADAPTER_ADDRESSES*       adapter       = NULL;
   IP_ADAPTER_UNICAST_ADDRESS* adr           = NULL;
   ULONG                       adapter_size = 0;
   ULONG                       err           = 0;
   SOCKADDR_IN*                sockaddr  = NULL;

   err = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, NULL, &adapter_size);
   adapters = (IP_ADAPTER_ADDRESSES*)malloc(adapter_size);
   err = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, adapters, &adapter_size);

   for (adapter = adapters; NULL != adapter; adapter = adapter->Next)
   {
       if (adapter->IfType     == IF_TYPE_SOFTWARE_LOOPBACK) continue; // Skip Loopback
       if (adapter->OperStatus != IfOperStatusUp) continue;            // Live connection only  

       for (adr = adapter->FirstUnicastAddress;adr != NULL; adr = adr->Next)
       {
           sockaddr = (SOCKADDR_IN*)(adr->Address.lpSockaddr);
           char    ipstr [INET6_ADDRSTRLEN] = { 0 };
           wchar_t ipwstr[INET6_ADDRSTRLEN] = { 0 };
           inet_ntop(AF_INET, &(sockaddr->sin_addr), ipstr, INET_ADDRSTRLEN);
           mbstowcs(ipwstr, ipstr, INET6_ADDRSTRLEN);
           wstring wstr(ipwstr);
           if (wstr != "0.0.0.0") ips.push_back(wstr);                      
       }
   }

   free(adapters);
   adapters = NULL; }

Winsock specific:

// Init WinSock
WSADATA wsa_Data;
int wsa_ReturnCode = WSAStartup(0x101,&wsa_Data);

// Get the local hostname
char szHostName[255];
gethostname(szHostName, 255);
struct hostent *host_entry;
host_entry=gethostbyname(szHostName);
char * szLocalIP;
szLocalIP = inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
WSACleanup();

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to sockets

JS file gets a net::ERR_ABORTED 404 (Not Found) mysqld_safe Directory '/var/run/mysqld' for UNIX socket file don't exists WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 TypeError: a bytes-like object is required, not 'str' Failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED No connection could be made because the target machine actively refused it 127.0.0.1 Sending a file over TCP sockets in Python socket connect() vs bind() java.net.SocketException: Connection reset by peer: socket write error When serving a file How do I use setsockopt(SO_REUSEADDR)?

Examples related to networking

Access HTTP response as string in Go Communication between multiple docker-compose projects Can't access 127.0.0.1 How do I delete virtual interface in Linux? ConnectivityManager getNetworkInfo(int) deprecated Bridged networking not working in Virtualbox under Windows 10 Difference between PACKETS and FRAMES How to communicate between Docker containers via "hostname" java.net.ConnectException: failed to connect to /192.168.253.3 (port 2468): connect failed: ECONNREFUSED (Connection refused) wget: unable to resolve host address `http'