首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

獲取遠程機器 MAC 地址的 C++ 實現原理與代碼詳解

     編輯:VC++

前言

在局域網開發中,經常需要根據 IP 地址獲取遠程主機的 MAC 地址。Windows 提供了 SendARP API 可以直接發送 ARP 請求並獲取物理地址。本文將詳細解析一個完整的控制台程序示例,展示如何初始化 Winsock、解析主機名、發送 ARP 請求並格式化輸出 MAC 地址。

核心代碼邏輯

1. 初始化 Winsock 與參數解析

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <iphlpapi.h>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Iphlpapi.lib")

void main(int argc, char **argv) {
    int numberOfHost = 1;
    struct hostent *remoteHostent;

    // 處理命令行參數
    if (argc == 3) numberOfHost = atoi(argv[2]);
    if (argc > 3 || argc < 2) {
        printf("RmtHost v0.2 - Get remote HostName /MacAddress\n");
        printf("by ShotgunLabs ( Shotgun@xici.net )\n\n");
        printf("Usage :\n\tRmtHost.exe [RemoteIP] [NUMBEROFHOSTTOSCAN]\n\n");
        printf("Example:\n\tRmtHost.exe 192.168.0.3\n");
        printf("\tRmtHost.exe 192.168.0.3 255\n\n");
        exit(0);
    }

    // 初始化 SOCKET
    WSADATA wsaData;
    int iRet = WSAStartup(MAKEWORD(2,1), &wsaData);
    if (iRet != 0) {
        printf("WSAStartup Error:%d\n", GetLastError());
        exit(0);
    }
    ...
}

程序啟動時解析命令行參數:第一個參數為目標 IP,第二個可選參數指定掃描的主機數量(默認為 1)。隨後調用 WSAStartup 初始化 Winsock 2.1 環境。

2. 迭代掃描並獲取主機名

int nRemoteAddr = inet_addr(argv[1]);
remoteHostent = (struct hostent*)malloc(sizeof(struct hostent));
struct in_addr sa;

for (int i = 0; i < numberOfHost; i++) {
    // 獲取遠程機器名
    sa.s_addr = nRemoteAddr;
    printf("\nIpAddress : %s\n", inet_ntoa(sa));
    remoteHostent = gethostbyaddr((char*)&nRemoteAddr, 4, AF_INET);
    if (remoteHostent)
        printf("HostName : %s\n", remoteHostent->h_name);
    else
        printf("gethostbyaddr Error:%d\n", GetLastError());
    ...
}

使用 inet_addr 將字符串 IP 轉換為網絡字節序整數。循環中調用 gethostbyaddr 進行反向 DNS 解析,嘗試獲取主機名。

3. 發送 ARP 請求獲取 MAC 地址

// 發送ARP查詢包獲得遠程MAC地址
unsigned char macAddress[6];
ULONG macAddLen = 6;
iRet = SendARP(nRemoteAddr, (unsigned long)NULL, (PULONG)&macAddress, &macAddLen);
if (iRet == NO_ERROR) {
    printf("MacAddress: ");
    for (int i = 0; i < 6; i++) {
        printf("%.2x", macAddress[i]);
        if (i < 5) printf("-");
    }
    printf("\n");
} else {
    printf("SendARP Error:%d\n", GetLastError());
}
// 移動到下一個 IP(網絡字節序加 1)
nRemoteAddr = htonl(ntohl(nRemoteAddr) + 1);

SendARP 是核心函數,它向目標 IP 發送 ARP 請求並填充 macAddress 緩衝區。成功後以 XX-XX-XX-XX-XX-XX 格式輸出。最後將 IP 地址加 1 以便掃描下一台主機。

編譯與運行說明

  • 需鏈接 ws2_32.lib 和 Iphlpapi.lib。
  • 以管理員權限運行可提高 ARP 請求的成功率。
  • 示例:RmtHost.exe 192.168.1.100 10 將掃描 192.168.1.100 到 192.168.1.109 共 10 台主機。

常見問題排查

  1. SendARP 返回錯誤:目標主機可能不在同一子網、防火牆攔截 ARP、或目標離線。
  2. 獲取主機名失敗:網絡中無 DNS 服務器或目標未註冊 PTR 記錄。
  3. 掃描速度慢:ARP 請求有超時重試機制,批量掃描建議使用異步或多線程優化。

本示例代碼簡潔地演示了 Windows 平台下 ARP 掃描的基本流程,適合作為網絡工具開發的起點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved