使用 SendARP 获取 MAC 地址(使用SendARP API函数,很多相关文章)
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
);
1
2
3
4
5
6
四个参数分别是:目的 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 */
} else
DestIpString = argv[i];
} /* end for */
} else
usage(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]);
else
printf("%.2X-", (int) bPhysAddr[i]);
}
} else
printf
("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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
更多参考
SendARP function
地址解析协议
---------------------
作者:一去丶二三里
来源:CSDN
原文:https://blog.csdn.net/liang19890820/article/details/80683512
版权声明:本文为博主原创文章,转载请附上博文链接!
使用 SendARP 获取 MAC 地址(使用SendARP API函数,很多相关文章)的更多相关文章
- C#获取MAC地址的几种方法
首先需要用到的一些方法和类: public enum NCBCONST { NCBNAMSZ = 16, MAX_LANA = 254, NCBENUM = 0x37, NRC_GOODRET = 0 ...
- C#中通过SendARP读取MAC地址
C#中通过SendARP读取MAC地址: using System.Runtime.InteropServices; publicstaticstring GetMacBySendARP(string ...
- c++ windows 获取mac地址
c++ windows 获取mac地址 GetAdaptersInfo 用windows api获取mac地址和硬盘id编号 aa
- android获取Mac地址和IP地址
获取Mac地址实际项目中测试了如下几种方法:(1)设备开通Wifi连接,获取到网卡的MAC地址(但是不开通wifi,这种方法获取不到Mac地址,这种方法也是网络上使用的最多的方法) //根据Wifi信 ...
- 在Web中获取MAC地址
很多时候都很难琢磨客户在想什么,也许是自己业务经验不足,也许是客户要显示出他在软件方面也非常的专业.记得以前听过一个故事,说一个富人想娶个媳妇,然后他比较钟意的有三个女人,然后就想从三个女人中选一个, ...
- 获取mac地址方法之一 GetAdaptersInfo()
GetAdaptersInfo -20151116 防止返回的mac出现null 20151116 From:http://blog.csdn.net/weiyumingwww/article/det ...
- (转)【Android】获取Mac地址【2】
[Android]获取Mac地址[2] 之前写了[Android]获取Mac地址[1]有些不够详细,现在贴上一些其他代码,仅供参考. (1) 调用android 的API: NetworkInterf ...
- php怎么获取mac地址?
如何用php获取mac地址呢?大家知道mac地址是电脑在全球范围的唯一标识,所以这个就非常实用,比如说要做一个投票功能,那mac地址是必不可少 的,如果单纯的靠ip地址来判断这个肯定是不准确的,水分太 ...
- C# 获取MAC地址
/********************************************************************** * C# 获取MAC地址 * 说明: * 在C#中获取本 ...
随机推荐
- mysql性能监控qps,tps,iops
qps 每秒处理的查询数tps 每秒处理的事务数IOPS,每秒磁盘进行的I/O操作次数 给个方法或者思路,用啥工具或者命令,如何看,值是多少属于正常范围之内呢? Information from we ...
- VisualSVN破解
先讲下破解原理 首先,去VisualSVN官网下载最新版本. 传送门:http://www.visualsvn.com/server/download/ 定位到VisualSVN安装目录,C:\Pro ...
- Ansible Playbook 使用循环语句
如下,with_items 是循环的对象,with_items 是 python list 数据结构,task 会循环读取 list 里面的值,key 的名称是 item [root@localhos ...
- [Python] Python 之 function, unbound method 和 bound method
首先看一下以下示例.(Python 2.7) #!/usr/bin/env python # -*- coding: utf-8 -*- class C(object): def foo(self): ...
- php危险的函数和类 disable_functions/class
phpinfo()功能描述:输出 PHP 环境信息以及相关的模块.WEB 环境等信息.危险等级:中 passthru()功能描述:允许执行一个外部程序并回显输出,类似于 exec().危险等级:高 e ...
- iOS提交审核:您的 App 正在使用广告标识符 (IDFA)
本文转载至 https://mp.weixin.qq.com/s?__biz=MzA3NzM0NzkxMQ==&mid=401172721&idx=1&sn=a369cf1b ...
- iOS - 栈顶VC控制器的获取
iOS 获取当前顶层的ViewController #pragma mark - topVC - (UIViewController *)theTopviewControler { UIViewCon ...
- EPON ONU软件升级的若干优化方案
1 说明 目前EPON ONU软件升级主要有IP方式(如SNMP/TR069)和TFTP+OAM两种.前者需占用大量IP地址,且配置ONU的IP地址需要手工操作,给业务开通和系统维护带来较大不便:后者 ...
- C++空类
class Empty { public: Empty(); // 缺省构造函数 Empty( const Empty& ); // 拷贝构造函数 ~Empty(); // 析构函数 Empt ...
- 【VI】如何再执行上一个(历史)命令(已解决)
输入命令提示符( : )+ 上下箭头(<Up/Down>键) 输入 :his 或者 :history 查看历史