使用 SendARP 获取 MAC 地址
ARP 协议
地址解析协议(ARP)是通过解析网路层地址来找寻数据链路层地址的一个在网络协议包中极其重要的网络传输协议。ARP 最初在 1982 年的 RFC 826 中提出并纳入互联网标准 STD 37. ARP 也可能指是在多数操作系统中管理其相关地址的一个进程。
ARP 是通过网络地址(例:IPv4)来定位 MAC 地址(也称为乙太地址)。ARP 已经在很多网路层和数据链接层之间得以实现,包括:IPv4,Chaosnet,DECnet 和 Xerox PARC Universal Packet (PUP) 使用 IEEE 802 标准,光纤分布式数据接口,X.25,帧中继和异步传输模式(ATM),IEEE 802.3 和 IEEE 802.11 标准上 IPv4 占了多数流量。
在 IPv6 中邻居发现协议(NDP)用于代替地址解析协议。
ARP 基本原理
在每台安装有 TCP/IP 协议的计算机或路由器里都有一个 ARP 缓存表,表里的 IP 地址与 MAC 地址是一对应的,如下表所示:
主机名称 | IP 地址 | MAC 地址 |
---|---|---|
A | 192.168.38.10 | 00-AA-00-62-D2-02 |
B | 192.168.38.11 | 00-BB-00-62-C2-02 |
C | 192.168.38.12 | 00-CC-00-62-C2-02 |
D | 192.168.38.13 | 00-DD-00-62-C2-02 |
E | 192.168.38.14 | 00-EE-00-62-C2-02 |
… | … | … |
以主机 A(192.168.38.10)向主机 B(192.168.38.11)发送数据为例:
当发送数据时,主机 A 会在自己的 ARP 缓存表中寻找是否有目标 IP 地址。如果找到就知道目标 MAC 地址为(00-BB-00-62-C2-02),直接把目标 MAC 地址写入帧里面发送就可。
如果在 ARP 缓存表中没有找到相对应的IP地址,主机 A 就会在网络上发送一个广播(ARP request),目标 MAC 地址是“FF.FF.FF.FF.FF.FF”,这表示向同一网段内的所有主机发出这样的询问:“192.168.38.11 的 MAC 地址是什么?”
网络上其他主机并不响应ARP询问,只有主机 B 接收到这个帧时,才向主机 A 做出这样的回应(ARP response):“192.168.38.11 的 MAC 地址是 00-BB-00-62-C2-02”,此回应以单播方式。这样,主机A就知道主机 B 的 MAC 地址,它就可以向主机B发送信息。同时它还更新自己的 ARP 高速缓存(ARP cache),下次再向主机B发送信息时,直接从 ARP 缓存表里查找就可。
ARP 缓存表采用老化机制,在一段时间内如果表中的某一行没有使用,就会被删除,这样可以大大减少 ARP 缓存表的长度,加快查询速度。
SendARP 函数
SendARP 函数通过发送一个地址解析协议(ARP)请求,来获得与指定的目的地 IPv4 地址相对应的物理地址。
语法格式如下:
DWORD SendARP(_In_ IPAddr DestIP,_In_ IPAddr SrcIP,_Out_ PULONG pMacAddr,_Inout_ PULONG PhyAddrLen
);
四个参数分别是:目的 IP 地址、源 IP 地址(一般默认为 0)、物理地址缓冲区指针、以及缓冲区长度。
获取 MAC 地址
获取与指定的 IPv4 地址相关联的硬件或 MAC 地址:
代码如下:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")void usage(char *pname)
{printf("Usage: %s [options] ip-address\n", pname);printf("\t -h \t\thelp\n");printf("\t -l length \tMAC physical address length to set\n");printf("\t -s src-ip \tsource IP address\n");exit(1);
}int __cdecl main(int argc, char **argv)
{DWORD dwRetVal;IPAddr DestIp = 0;IPAddr SrcIp = 0; /* default for src ip */ULONG MacAddr[2]; /* for 6-byte hardware addresses */ULONG PhysAddrLen = 6; /* default to length of six bytes */char *DestIpString = NULL;char *SrcIpString = NULL;BYTE *bPhysAddr;unsigned int i;if (argc > 1) {for (i = 1; i < (unsigned int) argc; i++) {if ((argv[i][0] == '-') || (argv[i][0] == '/')) {switch (tolower(argv[i][1])) {case 'l':PhysAddrLen = (ULONG) atol(argv[++i]);break;case 's':SrcIpString = argv[++i];SrcIp = inet_addr(SrcIpString);break;case 'h':default:usage(argv[0]);break;} /* end switch */} elseDestIpString = argv[i];} /* end for */} elseusage(argv[0]);if (DestIpString == NULL || DestIpString[0] == '\0')usage(argv[0]);DestIp = inet_addr(DestIpString);memset(&MacAddr, 0xff, sizeof (MacAddr));printf("Sending ARP request for IP address: %s\n", DestIpString);dwRetVal = SendARP(DestIp, SrcIp, &MacAddr, &PhysAddrLen);if (dwRetVal == NO_ERROR) {bPhysAddr = (BYTE *) & MacAddr;if (PhysAddrLen) {for (i = 0; i < (int) PhysAddrLen; i++) {if (i == (PhysAddrLen - 1))printf("%.2X\n", (int) bPhysAddr[i]);elseprintf("%.2X-", (int) bPhysAddr[i]);}} elseprintf("Warning: SendArp completed successfully, but returned length=0\n");} else {printf("Error: SendArp failed with error: %d", dwRetVal);switch (dwRetVal) {case ERROR_GEN_FAILURE:printf(" (ERROR_GEN_FAILURE)\n");break;case ERROR_INVALID_PARAMETER:printf(" (ERROR_INVALID_PARAMETER)\n");break;case ERROR_INVALID_USER_BUFFER:printf(" (ERROR_INVALID_USER_BUFFER)\n");break;case ERROR_BAD_NET_NAME:printf(" (ERROR_GEN_FAILURE)\n");break;case ERROR_BUFFER_OVERFLOW:printf(" (ERROR_BUFFER_OVERFLOW)\n");break;case ERROR_NOT_FOUND:printf(" (ERROR_NOT_FOUND)\n");break;default:printf("\n");break;}}return 0;
}
更多参考
- SendARP function
- 地址解析协议
使用 SendARP 获取 MAC 地址相关推荐
- wince下获取mac地址的简单方法!
下,可以通过访问注册表获取mac地址,可是非常可惜的是有些系统的注册表不提供这个键值,另外也可以通过 DeviceIoControl这类函数获得,但是所有方法要么不全面,要么不够简单或者有些平台bsp ...
- java 根据ip获取mac地址_利用java如何根据IP获取mac地址
利用java如何根据IP获取mac地址 发布时间:2020-11-25 15:49:42 来源:亿速云 阅读:74 作者:Leah 利用java如何根据IP获取mac地址?针对这个问题,这篇文章详细介 ...
- iOS7以下设备获取mac地址
注意,是iOS7以下的设备,直接上源码,获取mac地址都是为了唯一标识一个设备的,但iOS7设备的mac地址为 020000000000 MacAddress.h #include <sys/s ...
- C# 获取MAC地址
/*********************************************************************** C# 获取MAC地址* 说明:* 在C#中获取本机的M ...
- 获取mac地址方法之一 GetAdaptersInfo()
GetAdaptersInfo -20151116 防止返回的mac出现null 20151116 From:http://blog.csdn.net/weiyumingwww/article/det ...
- Python根据IP地址获取MAC地址
Python3根据IP地址获取MAC地址(不能获取本机IP,可以获取与本机同局域网设备IP的MAC) main.py #!/usr/bin/env python3 # -*- coding: utf- ...
- php获取手机的mac地址,Android手机获取Mac地址的方法
[导读]这篇文章主要为大家详细介绍了Android手机获取Mac地址的方法,具有一定的参考价值 最常用的方法,通过WiFiManager获取:/** * 通过WiFiManager获取mac地址 * ...
- Android获取MAC地址
(1) 调用android 的API: NetworkInterface. getHardwareAddress () 该API的level为9,只有android 2.3以上才有该接口 geMacF ...
- python获取mac地址_你知道怎么用Python获取计算机名,ip地址,mac地址吗
获取计算机名 # 获取计算机名,常用的方法有三种,但最常用的是第一种 import os import socket # method one name = socket.gethostname() ...
最新文章
- Java - 对象的创建
- oracle游标指针移动时机,oracle--游标(cursor)
- Emoji表情符号兼容方案(适用ios,android,wp等平台)
- python大数据项目_(价值1280)大数据项目实战之Python金融应用编程
- 游戏角色坐标的保存间隔_游戏岗位看这里鸭——
- Python中的join函数
- C#控制网页并自动输入
- 通过修改word文件,来屏蔽宏代码
- 拓端tecdat|R语言中使用非凸惩罚函数回归(SCAD、MCP)分析前列腺数据
- Android广播时间——实现强制下线功能
- 彼时彼刻恰似此时此刻
- 对于解决新版unity5.x的license error 问题
- 辗转相除法——求最大公约数
- 软件设计与体系结构第二版董威_董威-软件设计与体系结构(第2版)-PPT课件.zip-3-4-形式化方法.ppt...
- 4.5.2.3_黑白滤镜
- 微课登陆显示服务器繁忙,老师为什么教别人孩子容易,教自家孩子却这么难?| 公益微课...
- 算法中的大O是什么意思
- 【剑指Offer】个人学习笔记_15_二进制中1的个数
- Is Sampling Heuristics Necessary in Training Deep Object Detectors? 论文笔记
- 伏拉夫背景音乐计算机版,SONOS ZonePlayer 120
热门文章
- [五一随想] 生活长乐
- zookeeper之watcher
- Android MVVM框架搭建(十)Hilt、ViewBinding、Activity Result API
- 【PyTorch】关于函数 datasets.IMDB.splits()
- 虚拟化kvm-虚拟化概述
- 参考文献起止页码怎么写_期刊作为参考文献要求有年卷期和起止页码,怎么查这些页码什么的...
- windows硬盘数据安全处理工具
- train data 和 model bias 对 Mutilayer Perceptrons 的影响
- 人脸识别图片base64编码,Java实现
- java图形验证码去除干扰,使用python 对验证码图片进行降噪处理