获取本地计算机的IP地址

时间:2020-03-06 14:36:37  来源:igfitidea点击:

在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()函数。