使用 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#中获取本 ...
随机推荐
- Masonry — 使用纯代码进行iOS应用的autolayout自适应布局
本文转载至 http://www.ios122.com/2015/09/masonry/ 简化iOS应用使用纯代码机型自适应布局的工作,使用一种简洁高效的语法替代NSLayoutConstrain ...
- 关于RabbitMQ交换机的理解
RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.消息中间件主要用于组件之间的解耦,消 ...
- [sql异常]SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的
//执行远程数据库表查询 SELECT * FROM OPENDATASOURCE('SQLOLEDB', 'Data Source=数据库地址;User ID=sa;password=sa' ).n ...
- QT开发之旅四邮件发送工具
终于有了一个晚上安静的写写程序,最近一直忙着公司商务上的事情,一直想用QT实现一个调用最底层socket通信来实现的邮件发送程序,以前用C#写过,微软都封装好的,不知道底层是如何实现的,只知道调用方法 ...
- 使用gdb调试theos tweak插件
查看设备日志tail -f /var/log/syslog或者 Mobilesubstrate injects your dylib into the target process. Debuggin ...
- Elasticsearch学习之ES节点类型以及各种节点的分工
ES各种节点的分工 1. 客户端节点 当主节点和数据节点配置都设置为false的时候,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户节点表现为智能负载平衡器.独立的客户端节点在一 ...
- LeetCode 38 Count and Say(字符串规律输出)
题目链接:https://leetcode.com/problems/count-and-say/?tab=Description 1—>11—>21—>1211—>111 ...
- LeetCode 21 Merge Two Sorted Lists (有序两个链表整合)
题目链接 https://leetcode.com/problems/merge-two-sorted-lists/?tab=Description Problem: 已知两个有序链表(链表中的数 ...
- [原]git的使用(一)---建立本地仓库、add和commit、status和git diff、版本回退使用git reset
在window下已经安装了git的环境 1.建立本地仓库 mkdir test #建立test目录 cd test #进入目录 git init # ...
- loop设备及losetup命令
1. loop设备介绍 在类 UNIX 系统里,loop 设备是一种伪设备(pseudo-device),或者也可以说是仿真设备.它能使我们像块设备一样访问一个文件.在使用之前,一个 loop 设备必 ...