Visual C++ 2017网络编程实战
上QQ阅读APP看书,第一时间看更新

2.2 获取本机子网IP地址和子网掩码

子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,用来指明一个IP地址的哪些位标识的是主机所在的子网以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。

GetAdaptersInfo函数

GetAdaptersInfo函数用来检索本地计算机的适配器信息,函数声明如下:

    ULONG GetAdaptersInfo(PIP_ADAPTER_INFO  pAdapterInfo,  PULONG  pOutBufLen);

其中,pAdapterInfo指向接收IP适配器信息结构链表的缓冲区的指针,注意pAdapterInfo指向的是一个链表节点的指针;参数pOutBufLen指向ulong变量的指针,该变量指定pAdapterInfo参数指向的缓冲区大小,如果此大小不足以保存适配器信息,pAdapterInfo将使用所需的大小填充此变量,并返回错误代码ERROR_BUFFER_OVERFLOW。如果函数成功,返回值为ERROR_SUCCESS。如果函数失败,返回值是以下错误代码之一:

·ERROR_BUFFER_OVERFLOW:表示接收适配器信息的缓冲区太小。如果poutbuflen参数指示的缓冲区大小太小,无法容纳适配器信息,或者pAdapterInfo参数为空指针,返回此错误代码时,pOutBufLen参数指向所需的缓冲区大小。因此,我们可以让pAdapterInfo为NULL来获得所需缓冲区的大小,然后就可以给pAdapterInfo分配空间了。

·ERROR_INVALID_DATA:检索到无效的适配器信息。

·ERROR_INVALID_PARAMETER:存在某个参数无效。如果pOutBufLen参数为空指针,或者调用进程对pOutBufLen指向的内存没有读/写访问权限,或者调用进程对pAdapterInfo参数指向的内存没有写访问权限,就返回此错误。

·ERROR_NO_DATA:本地计算机不存在适配器信息。

·ERROR_NOT_SUPPORTED:本地计算机上运行的操作系统不支持GetAdaptersInfo函数。

这个函数在调用的时候,一般分两次调用。第一次调用的时候pAdapterInfo设为NULL,这样pOutBufLen将指向获得实际所需缓冲区大小,在第二次调用前就可以为pAdapterInfo分配实际所需大小了。下面看例子。

【例2.2】获取本机IP地址和对应掩码

(1)新建一个控制台工程test。

(2)打开test.cpp,输入代码:

    #include "stdafx.h"
    #include <atlstr.h>
    #include <IPHlpApi.h>
    #include <iostream>
    #pragma comment(lib, "Iphlpapi.lib")

    using namespace std;

    int _tmain(int argc, _TCHAR* argv[])
    {
    CString szMark;
    PIP_ADAPTER_INFO pAdapterInfo=NULL;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD dwRetVal = 0;

    ULONG ulOutBufLen  = sizeof(IP_ADAPTER_INFO);

    // 第一次调用GetAdapterInfo获取ulOutBufLen大小
    if (GetAdaptersInfo(NULL, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
         pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);

    if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
    {
         pAdapter = pAdapterInfo;
         while (pAdapter)
         {
              PIP_ADDR_STRING pIPAddr;
              pIPAddr = &pAdapter->IpAddressList;
              while (pIPAddr)
              {
                  cout << "IP:" << pIPAddr->IpAddress.String << endl;
                  cout << "Mask:" << pIPAddr->IpMask.String << endl;
                  cout << endl;
                  pIPAddr = pIPAddr->Next;
              }
              pAdapter = pAdapter->Next;
         }
    }

    if (pAdapterInfo)
         free(pAdapterInfo);

    getchar();
    return 0;
    }

(3)保存工程并运行,结果如图2-4所示。

图2-4

从这个例子和上个例子可以看出,获取本机IP地址的方法不止一种。