在Windows系统中,通过网络邻居可以方便地查看本地网络中的共享资源和计算机。通过使用Windows API中的一些网络相关函数,我们可以实现枚举网络邻居信息的功能,获取连接到本地网络的其他计算机的相关信息。本文将介绍一个简单的C++程序,使用Windows API枚举网络邻居信息,并获取对端名称、本机名称、主机名称以及主机IP等信息。
引言
首先,我们需要了解一下几个与网络邻居信息有关的Windows API函数:
NETRESOURCE
结构体是 Windows 网络 API 中的一个结构体,用于描述网络资源的信息。它在网络资源的枚举和连接等操作中经常被使用。
结构体定义
typedef struct _NETRESOURCE {DWORD dwScope;DWORD dwType;DWORD dwDisplayType;DWORD dwUsage;LPTSTR lpLocalName;LPTSTR lpRemoteName;LPTSTR lpComment;LPTSTR lpProvider;
} NETRESOURCE, *LPNETRESOURCE;
结构体成员
dwScope
:指定资源的可见性。可能的取值为:RESOURCE_CONNECTED
:表示已连接的资源。RESOURCE_CONTEXT
:表示会话特定的资源。
dwType
:指定资源的类型。可能的取值为:RESOURCETYPE_ANY
:表示任何类型的资源。RESOURCETYPE_DISK
:表示磁盘资源。RESOURCETYPE_PRINT
:表示打印机资源。
dwDisplayType
:指定资源的显示类型。可能的取值为:RESOURCEDISPLAYTYPE_GENERIC
:表示通用资源。RESOURCEDISPLAYTYPE_DOMAIN
:表示域。
dwUsage
:指定资源的使用类型。可能的取值为:RESOURCEUSAGE_CONNECTABLE
:表示资源可以连接。RESOURCEUSAGE_CONTAINER
:表示资源是一个容器,可以包含其他资源。
lpLocalName
:指定本地驱动器或打印机的本地名称。lpRemoteName
:指定远程共享资源的网络名称。lpComment
:指定资源的注释。lpProvider
:指定提供资源的网络提供程序的名称。
WNetOpenEnum
是 Windows 网络功能中的一个API函数,WNetOpenEnum
通过指定的参数打开一个用于列举网络资源的枚举句柄。这个句柄可以在后续的操作中用于获取网络资源的枚举信息。
函数原型
DWORD WNetOpenEnum(DWORD dwScope,DWORD dwType,DWORD dwUsage,LPNETRESOURCE lpNetResource,LPHANDLE lphEnum
);
参数说明
dwScope
:指定枚举的范围,可以是RESOURCE_CONNECTED
、RESOURCE_GLOBALNET
、RESOURCE_REMEMBERED
、RESOURCE_CONTEXT
中的一个。dwType
:指定枚举资源的类型,可以是RESOURCETYPE_DISK
、RESOURCETYPE_PRINT
、RESOURCETYPE_ANY
中的一个。dwUsage
:指定枚举资源的使用类型,可以是RESOURCEUSAGE_CONNECTABLE
、RESOURCEUSAGE_CONTAINER
、RESOURCEUSAGE_NOLOCALDEVICE
、RESOURCEUSAGE_SIBLING
中的一个。lpNetResource
:指向NETRESOURCE
结构的指针,用于指定枚举的起始位置。如果为NULL
,则从所有资源的最顶层开始枚举。lphEnum
:指向句柄的指针,用于接收枚举句柄。
返回值
如果函数调用成功,返回 NO_ERROR
,否则返回一个错误代码,可以通过 GetLastError
函数获取详细信息。
WNetEnumResource
是 Windows 网络功能中的 API 函数之一,用于通过枚举句柄获取网络资源的详细信息,包括资源的类型、用途、本地名、远程名等信息。
函数原型
DWORD WNetEnumResource(HANDLE hEnum,LPDWORD lpcCount,LPVOID lpBuffer,LPDWORD lpBufferSize
);
参数说明
hEnum
:枚举句柄,通过WNetOpenEnum
函数获取的句柄。lpcCount
:指向一个变量的指针,该变量用于接收枚举的资源数目。lpBuffer
:指向一个缓冲区的指针,用于接收枚举的资源信息。lpBufferSize
:指向一个变量的指针,该变量用于指定或接收缓冲区的大小。
返回值
如果函数调用成功,返回 NO_ERROR
,否则返回一个错误代码,可以通过 GetLastError
函数获取详细信息。
WNetCloseEnum
函数用于关闭由 WNetOpenEnum
函数打开的网络资源的枚举句柄。在使用 WNetOpenEnum
函数枚举网络资源后,当不再需要使用枚举句柄时,应该通过调用 WNetCloseEnum
函数来释放资源,避免内存泄漏。
函数定义
DWORD WNetCloseEnum(HANDLE hEnum
);
参数
hEnum
:网络资源的枚举句柄,该句柄是由WNetOpenEnum
函数返回的。
返回值
如果函数调用成功,返回 NO_ERROR
,否则返回错误代码,可以通过 GetLastError
函数获取详细的错误信息。
代码实现
以下是一个简单的C++程序,使用上述API函数实现了枚举网络邻居信息的功能。该程序通过遍历枚举得到的网络资源信息,获取对端名称、本机名称、主机名称以及主机IP等信息,并输出到控制台。
#include <iostream>
#include <Windows.h>
#include <winnetwk.h>#pragma comment(lib,"Mpr.lib")
#pragma comment(lib,"Ws2_32.lib")// 枚举网络邻居
BOOL EnumNetResource()
{NETRESOURCE *NetResource = NULL;HANDLE hEnum;unsigned int i;char szHostName[MAX_PATH] = { 0 };hostent *host = NULL;char *lpszIP = NULL;// 通过WSAStartup函数完成对Winsock服务的初始化WSADATA wsaData = { 0 };WSAStartup(MAKEWORD(2, 2), &wsaData);// 指定枚举范围, 获取枚举句柄WNetOpenEnum(RESOURCE_CONTEXT, NULL, NULL, NULL, &hEnum);if (hEnum){DWORD Count = 0xFFFFFFFF;DWORD BufferSize = 2048;BYTE *pBuffer = new BYTE[2048];// 根据设置的枚举返回, 获取枚举信息WNetEnumResource(hEnum, &Count, pBuffer, &BufferSize);NetResource = (NETRESOURCE*)pBuffer;for (i = 0; i < BufferSize / sizeof(NETRESOURCE); i++, NetResource++){// 判断资源类型是否是所有资源 以及 判断资源使用类型是否是容器资源if (NetResource->dwUsage == RESOURCEUSAGE_CONTAINER && NetResource->dwType == RESOURCETYPE_ANY){if (NetResource->lpRemoteName){// 获取远程主机名RtlZeroMemory(szHostName, MAX_PATH);lstrcpy(szHostName, (char *)((DWORD64)NetResource->lpRemoteName + 2));// 根据主机名获取IP地址信息host = gethostbyname(szHostName);if (host == NULL){std::cout << "错误代码" << std::endl;continue;}// 将Ipv4网络地址转换为Internet标准点分十进制格式的ASCII字符串lpszIP = inet_ntoa(*(in_addr *)host->h_addr_list[0]);std::cout << "对端名称: " << NetResource->lpRemoteName<< " 本机名称: " << NetResource->lpLocalName<< " 主机名称: " << szHostName<< " 主机IP: " << lpszIP<< std::endl;}}}// 释放内存并关闭句柄delete[]pBuffer;pBuffer = NULL;WNetCloseEnum(hEnum);}return TRUE;
}int main(int argc, char *argv[])
{EnumNetResource();system("pause");return 0;
}
结语
通过这个简单的程序,我们可以了解如何使用Windows API函数来枚举网络邻居信息。这对于需要在程序中获取网络中其他计算机信息的场景是非常有用的。在实际应用中,可以根据需要进一步扩展和优化代码,以满足特定的功能需求。