[Linux]ARP协议

概念:

1. ARP协议(地址解析协议):由IP地址转换为MAC地址的协议。IP地址:网络号+主机号。MAC地址:数据链路层的物理地址(硬件地址)。IP协议使用了ARP协议,因此被划归为网络层,但其用途是从网络层使用的IP地址解析出数据链路层的硬件地址,因此有些也将其划归为数据链路层。与ARP协议成对的协议为RARP,它是从MAC地址到IP地址的转换。

2. 网络层使用的是IP地址,但在实际网络的链路上传送数据帧时,最终还是使用网络的硬件地址。但IP地址和网络的硬件地址本身存在格式上的不同,也没有什么直接的映射关系。同时,网络上也有不同的主机加入进来,或撤走一些主机,更换网络适配器也会使硬件地址改变,因此引入了ARP协议,ARP协议主要解决此类问题的方法是在主机ARP高速缓存中存放一个从IP地址到硬件地址的映射表,并且这个映射表经常动态更新。

3. 每个主机都有一个ARP高速缓存,里面有局域网的主机和路由器的IP到硬件地址的映射表,这些都是该主机目前知道的一些地址。举个栗子哦,当主机A要给主机B发送报文时,主机A会在高速缓存中找是否有B的IP地址,如果有,则在ARP高速缓存中找到对应的硬件地址,再把这个地址写入MAC帧,然后通过局域网把该MAC帧发送到此硬件地址。也有可能查不到其IP地址,可能是由于主机B才入网,也可能是主机A刚加电,高速缓存还是空的。这种情况的话,主机A会自动运行ARP,来找出硬件地址。

(1) ARP在局域网中广播请求分组,找主机B的IP地址
(2) 在局域网上运行的主机都可以接收到ARP广播的消息,但只有主机B会有响应,其他主机则忽略该广播。
(3)主机B响应分组后,会在ARP响应分组中写入自己的硬件地址,此时的响应分组是单播的。刚刚广播是因为不知道主机是哪一个,现在知道了具体是哪一个主机后,主机B直接给主机A响应,因此是普通的单播。
(4) 主机A收到主机B的响应分组后,在ARP高速缓存中写入主机B的从IP地址到硬件地址的映射。为什么要将其写入ARP高速缓存呢,你发送数据报可能不止一次,当你发送完之后,主机B也给主机A响应后,可能也会发送数据报,这时如果没有ARP高速缓存,可能主机B也得以广播的方式先找到主机A的IP,再找硬件地址,这样就大大降低了网络的通信量,因此使用ARP来增加网络的通信量,也提供了方便。

4. ARP把保存在高速缓存中的每一个映射地址项目都设置生存时间,超过生存时间的项目就从高速缓存中删除掉。比如说主机A给主机B发数据,某一天,主机B的网络适配器坏了,B更换了一块,这时其硬件地址也被修改,这样的话高速缓存中存的还是原来的那个地址,这下你肯定找不到确定的硬件地址,有了生存时间后,你可以在限定的时间内找,如果找不到的话,就将原先的硬件地址删除,再重新广播发送ARP请求分组,重新找到B。继续上述的步骤,在高速缓存中写入正确的硬件地址即可。

5. ARP协议是解决局域网的情况,如果是不同的网络中的主机间的传送数据报呢?这里我们涉及到路由器的概念。主机A无法直接解析主机B的硬件地址,我们这时通过连接到主机A的路由器来进行转发,找到另一网络(通过将路由器A的IP转化为硬件地址,以便将IP数据报写入路由器A,A从转发表中找到下一跳路由B,同时解析出路由器B的硬件地址,于是再将数据报转发到路由B上),再通过路由器广播的方式(解析目的主机的硬件地址),找到正确的主机,传送数据报。

关于ARP,主要有四种典型情况:
1. 发送方是主机,把IP数据报发送到同一网络的另一个主机,此时主机A发送ARP请求分组,广播,找到目的主机的硬件地址
2. 发送方是主机,把IP数据报发送到不同网络的另一个主机,这时主机A发送ARP请求分组,找到主机A的路由器的硬件地址,剩下的工作由路由器完成。
3. 发送方是路由器,把IP数据报转发到同一网络的另一个主机,此时路由器发送ARP请求分组,广播,找到目的主机的硬件地址
4. 发送方是路由器,把IP数据报转发到不同网络的另一个主机,这时路由器R1发送ARP请求分组,找到下一跳路由器R2的硬件地址,剩下的工作由路由器R2完成。

下面我们来写个脚本来实现抓取主机MAC地址:

#!/bin/bash
net='192.168.127.'   //是我自己的主机IP
i=1
count=0
while [ $i -le 254 ]
doif [ $count -eq 20 ];thencount=0sleep 1fiping -c1 $net$i &   //检查网络是否连通let i++let count++donewait

我们可以使用arp -a来查看缓存中的MAC地址。如下:

这里写图片描述
这里写图片描述

其中显示incomplete的就是没有存入缓存中的。我们可以过滤一下。

#!/bin/bash
net='192.168.127.'
i=1
count=0
while [ $i -le 254 ]
doif [ $count -eq 20 ];thencount=0sleep 1fiping -c1 $net$i &let i++let count++donewait
arp -a | grep -v 'incomplete'

这次就会直接将没有连接的IP过滤掉,运行结果为:

这里写图片描述

这样我们就很好的抓取到了对应主机的MAC地址。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Makefile使用及多文件gdb 调试

文件内容 [koulocalhost makefile]$ cat 1.c #include "3.h" int main() {key_t key ftok(".",1);printf("%d\n",add(1,2));return 0; }[koulocalhost makefile]$ cat 2.c #include "3.h" int add(int a, int b) {return a b; } [k…

C++ 对引用的理解2

1.指针就是数据或代码在内存中的地址,指针变量指向的就是内存中的数据或代码。这里有一个关键词需要强调,就是内存,指针只能指向内存,不能指向寄存器或者硬盘,因为寄存器和硬盘没法寻址。 2.其实 C 代码中的大部分内容…

Ubuntu各版本主要差异

Ubuntu各版本主要差异 (重定向自Ubuntu , kubuntu与xubuntu的差别 ) Ubuntu官方考虑到使用者的不同需求,提供各种不同的发行版。这几种发行版本的差别在于桌面环境和预设安装的软体不同,但套件库是采用一样的,所以您当然可以在安…

[Linux]CRC校验

CRC(Cyclic Redundancy Check),循环冗余校验码,是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 CRC校验步骤: CRC分为两部分,前部分为信息码,后部分为校验码;设…

visual studio 2015 配置好qt5后, 第一次运行出现 无法打开源文件“QtWidgets/QApplication”和无法运行rc.exe的解决方案

无法打开源文件“QtWidgets/QApplication” a.在工程中右击项目,点击属性。 b.选择VC目录->包含目录 c.选择Qt安装目录中的头文件包含目录,一般为Qt版本号/版本号/编译器名/include 比如:E:\Qt\Qt5.6.3\5.6.3\msvc2015\include 在C\C>附…

怎么在vs中查看一个数组的所有元素

在监视窗口,我们想要查看所有的数组元素。 这个时候 int arr[] {1,2,3} arr只显示1 正确的方法 arr,10

[Linux]NAT和代理服务器

1. NAT:(Network Address Translation)是网络地址转换。 我们有这样一种场景,在专用网内部的一些主机本来已经分配到了本地IP地址,但现在又想和因特网上的主机通信,我们可以设法再申请一些全球IP地址&…

使用 C++的第三方库 jsoncpp的步骤以及出现的问题

Jsoncpp 是一个json解析库 下载地址为: http://sourceforge.net/projects/jsoncpp/ 方法一:使用Jsoncpp生成的lib文件 解压上面下载的Jsoncpp文件,在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln,用VS2008版本编译&am…

常用的友元重载运算符OSTREAM

对<<运算符重载&#xff0c;让他能和cout一起显示对象内容。 显示值可以使用show()&#xff0c;但是使用cout<<更方便。 ostream类对该运算符进行了重载&#xff0c;将其转换成输出工具。 cout就是一个ostream的对象&#xff0c;他可以自动识别所有的c基本类型。…

python字符串系列

1.find方法用于在长串中查找子串&#xff0c;返回子串中最左位置的下标&#xff0c;如果没找到&#xff0c;则返回-1 2.join方法用于在队列中添加元素 3.lower返回字符串的小写字母版 4.replace返回字符串中所有匹配项均被替换之后得到字符串 5.split将字符串分割成序列 6.stri…

C++ wstring 与 string 之间的相互转换.

方式一&#xff1a;调用Windows API #include <Windows.h> //将string转换成wstring wstring string2wstring(string str) { wstring result; //获取缓冲区大小&#xff0c;并申请空间&#xff0c;缓冲区大小按字符计算 int len MultiByteToWideChar(CP_ACP, 0,…

linux网络编程Internet Socket地址,套接字,和函数

文章内容节选《linux/UNIX 系统网络编程》 Internet domain socket地址有两种&#xff1a;IPv4 IPv6 IPv4被存储在结构体中&#xff0c; 该结构体在 netinet/in.h 中进行定义 cd usr/include/netinet/in.h struct in_addr {in_addr_t s_addr; //32位IPv4地址 }struct so…

浅谈socket网络编程函数参数(一)

socket函数解析 概念: 每个进程的进程空间里都有一个socket描述符表。套接字描述符表属于一个进程&#xff0c;而socket地址结构位于操作系统的内核缓冲。 函数原型 #include <sys/socket.h>int socket(int domain, int type, int protocol);函数参数 family参数 默…

C++ const 与 extern

C语言中&#xff0c; const修饰的全局变量是外部链接属性&#xff0c;比如在 a.c文件中有 const int m_a 10; 在b.c中想用这个全局变量&#xff0c; 在b.c中这样 extern const int m_a; 就可以使用a.c中的m_a C 语言中&#xff0c; const修饰的全局变量是内部链接属性&#x…

浅谈socket网络编程函数参数(二)

bind()函数 bind()函数把一个地址族中的特定地址赋给socket。 例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数解析 sockfd&#xff1a;即socket描述字&#xff0c…

对引用的理解3

对数组的引用&#xff0c; 相关语法 int main() { //引用于法// type &引用名 原名//数组的引用//1) 先定义一个数组int array[10];int (&refArray)[10] array;for (int i 0; i < 10; i) {array[i] i;}for (int i 0; i < 10; i) {cout << refArray[i…

运算符与,|与||的区别

|和&是位运算&#xff0c;运算结果是二进制数。 &&,||是逻辑运算&#xff0c;运算结果是真&#xff0c;或者假。 6&3110&0110102 6|3110|0111117&, &&和||计算时注意&#xff0c; 题目&#xff1a;条件1&&条件2&&条件3 如…

C++ 对引用的理解4

引用的注意事项 // 引用注意事项&#xff0c; 不能返回局部变量的引用 int & test3() { //因为局部变量出了函数体外 就会被销毁int a 10;return a; }// 引用注意事项&#xff0c; 返回值如果是引用&#xff0c; 那么函数可以作为左值进行运算 int & test4() {static…

关于argc和argv的输出

代码 #include <stdio.h>int main(int argc ,char * argv[]) {printf("argc ->%d\n",argc);for(int i 0; i < argc;i){printf("%s\n",argv[i]);}return 0; } 输出结果 [koulocalhost 8_6网络计算器]$ ./a.out 192.168.1.1 9000 argc ->…

C++ 对引用的理解5

常量引用 int main() { // int &m 10; // 错误&#xff0c; 引用必须引一块合法的内存空间&#xff08;什么是合法的内存空间&#xff0c; 这个10在程序中有内存吗&#xff1f;&#xff09;const int &m 10; //加入const后&#xff0c;语法就通过了&#xff0c;编译…