C/C++ 實現枚舉網上鄰居信息

在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_CONNECTEDRESOURCE_GLOBALNETRESOURCE_REMEMBEREDRESOURCE_CONTEXT 中的一個。
  • dwType:指定枚舉資源的類型,可以是 RESOURCETYPE_DISKRESOURCETYPE_PRINTRESOURCETYPE_ANY 中的一個。
  • dwUsage:指定枚舉資源的使用類型,可以是 RESOURCEUSAGE_CONNECTABLERESOURCEUSAGE_CONTAINERRESOURCEUSAGE_NOLOCALDEVICERESOURCEUSAGE_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函數來枚舉網絡鄰居信息。這對於需要在程序中獲取網絡中其他計算機信息的場景是非常有用的。在實際應用中,可以根據需要進一步擴展和優化代碼,以滿足特定的功能需求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章