获取本地计算机的IP地址
在C ++中,获取本地计算机的IP地址和子网掩码的最简单方法是什么?
我希望能够在本地网络中检测本地计算机的IP地址。在我的特定情况下,我的子网掩码为255.255.255.0,计算机的IP地址为192.168.0.5. 我需要以编程方式使它们具有两个值,以便将广播消息发送到我的网络(对于我的特殊情况,格式为192.168.0.255)
编辑:许多答案都没有给出我期望的结果,因为我有两个不同的网络IP。 Torial的代码成功了(它给了我两个IP地址)。谢谢。
编辑2:感谢Brian R. Bondy提供有关子网掩码的信息。
解决方案
我们可以使用gethostname后跟gethostbyname来获取本地接口内部IP。
该返回的IP可能与外部IP不同。要获取外部IP,我们必须与外部服务器通信,该服务器将告诉我们外部IP是什么。因为外部IP不是,而是路由器。
//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; }
我们也可以始终只使用127.0.0.1,它始终代表本地计算机。
Windows中的子网掩码:
我们可以通过查询以下注册表项的子项来获取子网掩码(以及网关和其他信息):
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ Interfaces
查找注册表值SubnetMask。
在Windows中获取接口信息的其他方法:
我们还可以使用以下方法检索所需的信息:
带有此选项的WSAIoctl:SIO_GET_INTERFACE_LIST
如何获得网络上本地计算机的IP地址似乎很好地描述了解决方案...
Winsock特定:
// 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();
from torial: If you use winsock, here's a way: http://tangentsoft.net/wskfaq/examples/ipaddr.html
至于问题的子网部分;没有平台不可知的方式来检索子网掩码,因为POSIX套接字API(所有现代操作系统都实现了)没有指定此功能。因此,我们将必须使用所使用平台上可用的任何方法。
我们不能只发送到INADDR_BROADCAST吗?诚然,它将在所有接口上发送,但这很少有问题。
否则,ioctl和SIOCGIFBRDADDR应该在* nix上为我们提供地址,而WSAioctl和SIO_GET_BROADCAST_ADDRESS在Win32上为我们提供地址。
另外,请注意,"本地IP"可能并不是特别独特的东西。如果我们在多个物理网络上(例如,有线+无线+蓝牙,或者具有很多以太网卡的服务器等),或者设置了TAP / TUN接口,则计算机可以轻松地拥有大量接口。
在DEV C ++中,我将纯C与WIN32结合使用,并提供以下代码:
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;
当我点击"显示IP"按钮时,它起作用了。但是第二次,程序退出(没有警告或者错误)。当我做:
//WSACleanup();
该程序不会退出,即使以最快的速度多次单击同一按钮。
因此WSACleanup()可能无法与Dev-C ++一起很好地工作。
这个问题比看起来要棘手,因为在许多情况下,没有"本地计算机的IP地址"那么多的不同IP地址。例如,我现在正在键入的Mac(这是一个非常基本的标准Mac设置),具有与其关联的以下IP地址:
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
...而不仅仅是弄清楚以上哪个是"真实IP地址",或者...它们都是"真实"且有用的;有些功能比其他功能有用,具体取决于我们将使用这些地址的目的。
以我的经验,获取本地计算机" IP地址"的最佳方法通常不是根本查询本地计算机,而是询问计算机程序正在与它查看计算机IP地址的方式进行交谈。例如如果我们正在编写客户端程序,请向服务器发送一条消息,要求服务器将我们请求的IP地址作为数据发送回去。这样,在与我们进行通信的计算机的上下文中,我们将知道相关的IP地址是什么。
也就是说,该技巧可能不适用于某些目的(例如,当我们不与特定计算机通信时),因此有时我们只需要收集与计算机关联的所有IP地址的列表即可。在Unix / Mac(AFAIK)下执行此操作的最佳方法是调用getifaddrs()并遍历结果。在Windows下,请尝试GetAdaptersAddresses()获得类似的功能。有关这两种用法的示例,请参见此文件中的GetNetworkInterfaceInfos()函数。