获取本地计算机的IP地址

在C ++中,获取本地计算机的IP地址和子网掩码的最简单方法是什么?


我希望能够在本地网络中检测本地计算机的IP地址。在我的特定情况下,我的子网掩码为255.255.255.0,计算机的IP地址为192.168.0.5。我需要以编程方式使它们具有两个值,以便将广播消息发送到我的网络(对于我的特殊情况,格式为192.168.0.255)


编辑:许多答案没有给出我期望的结果,因为我有两个不同的网络IP。Torial的代码成功了(它给了我两个IP地址)。谢谢。



开满天机
浏览 494回答 3
3回答

一只斗牛犬

所有基于gethostbyname的方法的问题在于,您不会获得分配给特定计算机的所有IP地址。服务器通常具有多个适配器。这是一个如何遍历主机上所有Ipv4和Ipv6地址的示例:void ListIpAddresses(IpAddresses& ipAddrs){&nbsp; IP_ADAPTER_ADDRESSES* adapter_addresses(NULL);&nbsp; IP_ADAPTER_ADDRESSES* adapter(NULL);&nbsp; // Start with a 16 KB buffer and resize if needed -&nbsp; // multiple attempts in case interfaces change while&nbsp; // we are in the middle of querying them.&nbsp; DWORD adapter_addresses_buffer_size = 16 * KB;&nbsp; for (int attempts = 0; attempts != 3; ++attempts)&nbsp; {&nbsp; &nbsp; adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addresses_buffer_size);&nbsp; &nbsp; assert(adapter_addresses);&nbsp; &nbsp; DWORD error = ::GetAdaptersAddresses(&nbsp; &nbsp; &nbsp; AF_UNSPEC,&nbsp;&nbsp; &nbsp; &nbsp; GAA_FLAG_SKIP_ANYCAST |&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; GAA_FLAG_SKIP_MULTICAST |&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; GAA_FLAG_SKIP_DNS_SERVER |&nbsp; &nbsp; &nbsp; &nbsp; GAA_FLAG_SKIP_FRIENDLY_NAME,&nbsp;&nbsp; &nbsp; &nbsp; NULL,&nbsp;&nbsp; &nbsp; &nbsp; adapter_addresses,&nbsp; &nbsp; &nbsp; &adapter_addresses_buffer_size);&nbsp; &nbsp; if (ERROR_SUCCESS == error)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; // We're done here, people!&nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; }&nbsp; &nbsp; else if (ERROR_BUFFER_OVERFLOW == error)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; // Try again with the new size&nbsp; &nbsp; &nbsp; free(adapter_addresses);&nbsp; &nbsp; &nbsp; adapter_addresses = NULL;&nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; // Unexpected error code - log and throw&nbsp; &nbsp; &nbsp; free(adapter_addresses);&nbsp; &nbsp; &nbsp; adapter_addresses = NULL;&nbsp; &nbsp; &nbsp; // @todo&nbsp; &nbsp; &nbsp; LOG_AND_THROW_HERE();&nbsp; &nbsp; }&nbsp; }&nbsp; // Iterate through all of the adapters&nbsp; for (adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next)&nbsp; {&nbsp; &nbsp; // Skip loopback adapters&nbsp; &nbsp; if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; }&nbsp; &nbsp; // Parse all IPv4 and IPv6 addresses&nbsp; &nbsp; for (&nbsp; &nbsp; &nbsp; IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;&nbsp;&nbsp; &nbsp; &nbsp; NULL != address;&nbsp; &nbsp; &nbsp; address = address->Next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; auto family = address->Address.lpSockaddr->sa_family;&nbsp; &nbsp; &nbsp; if (AF_INET == family)&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // IPv4&nbsp; &nbsp; &nbsp; &nbsp; SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);&nbsp; &nbsp; &nbsp; &nbsp; char str_buffer[INET_ADDRSTRLEN] = {0};&nbsp; &nbsp; &nbsp; &nbsp; inet_ntop(AF_INET, &(ipv4->sin_addr), str_buffer, INET_ADDRSTRLEN);&nbsp; &nbsp; &nbsp; &nbsp; ipAddrs.mIpv4.push_back(str_buffer);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; else if (AF_INET6 == family)&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // IPv6&nbsp; &nbsp; &nbsp; &nbsp; SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);&nbsp; &nbsp; &nbsp; &nbsp; char str_buffer[INET6_ADDRSTRLEN] = {0};&nbsp; &nbsp; &nbsp; &nbsp; inet_ntop(AF_INET6, &(ipv6->sin6_addr), str_buffer, INET6_ADDRSTRLEN);&nbsp; &nbsp; &nbsp; &nbsp; std::string ipv6_str(str_buffer);&nbsp; &nbsp; &nbsp; &nbsp; // Detect and skip non-external addresses&nbsp; &nbsp; &nbsp; &nbsp; bool is_link_local(false);&nbsp; &nbsp; &nbsp; &nbsp; bool is_special_use(false);&nbsp; &nbsp; &nbsp; &nbsp; if (0 == ipv6_str.find("fe"))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char c = ipv6_str[2];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c == '8' || c == '9' || c == 'a' || c == 'b')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; is_link_local = true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else if (0 == ipv6_str.find("2001:0:"))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; is_special_use = true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (! (is_link_local || is_special_use))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ipAddrs.mIpv6.push_back(ipv6_str);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Skip all other types of addresses&nbsp; &nbsp; &nbsp; &nbsp; continue;&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; // Cleanup&nbsp; free(adapter_addresses);&nbsp; adapter_addresses = NULL;&nbsp; // Cheers!}

喵喔喔

您可以使用gethostname后跟gethostbyname来获取本地接口内部IP。该返回的IP可能与您的外部IP不同。要获取外部IP,您必须与外部服务器通信,该服务器将告诉您外部IP是什么。因为外部IP不是您的,而是您的路由器。//Example: b1 == 192, b2 == 168, b3 == 0, b4 == 100struct IPv4{&nbsp; &nbsp; unsigned char b1, b2, b3, b4;};bool getMyIP(IPv4 & myIP){&nbsp; &nbsp; char szBuffer[1024];&nbsp; &nbsp; #ifdef WIN32&nbsp; &nbsp; WSADATA wsaData;&nbsp; &nbsp; WORD wVersionRequested = MAKEWORD(2, 0);&nbsp; &nbsp; if(::WSAStartup(wVersionRequested, &wsaData) != 0)&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; #endif&nbsp; &nbsp; if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; #ifdef WIN32&nbsp; &nbsp; &nbsp; WSACleanup();&nbsp; &nbsp; &nbsp; #endif&nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; struct hostent *host = gethostbyname(szBuffer);&nbsp; &nbsp; if(host == NULL)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; #ifdef WIN32&nbsp; &nbsp; &nbsp; WSACleanup();&nbsp; &nbsp; &nbsp; #endif&nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; //Obtain the computer's IP&nbsp; &nbsp; myIP.b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;&nbsp; &nbsp; myIP.b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;&nbsp; &nbsp; myIP.b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;&nbsp; &nbsp; myIP.b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;&nbsp; &nbsp; #ifdef WIN32&nbsp; &nbsp; WSACleanup();&nbsp; &nbsp; #endif&nbsp; &nbsp; return true;}您也可以始终只使用127.0.0.1,它始终代表本地计算机。Windows中的子网掩码:您可以通过查询以下注册表项的子项来获取子网掩码(以及网关和其他信息):HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ Interfaces查找注册表值SubnetMask。在Windows中获取接口信息的其他方法:您还可以通过以下方式检索所需的信息: WSAIoctl,带有以下选项:SIO_GET_INTERFACE_LIST
打开App,查看更多内容
随时随地看视频慕课网APP