ARP——地址解析协议
来源:互联网 发布:淘宝ecco鞋真假 编辑:程序博客网 时间:2024/06/05 04:07
目录:
1:概述
2:ARP报文格式
3:ARP解析缓存
4:ARP实现例程
5:总结
1、概述
1.1:当数据需要在不同的局域网中进行传输时,由于不同的局域网可能其物理地址(MAC地址)格式不同,所以制定IP地址,来统一标识网络中的设备;
1.2:ARP协议是通过给定的IP地址,找到所对应设备的物理地址:,通过以太网协议进行传输;
1.3:当上层协议通过IP协议发送数据报时,已经有目的设备的IP地址,但此时需要知道物理地址通过以太网协议把数据发送至目标设备,这时,原设备会发送一个包含ARP报文的广播帧,ARP报文包含目的设备的IP地址。ARP帧被所有设备接收,在对ARP帧进行分析后,具有该IP地址的设备应答报文的发送者,在应答报文中就有其物理地址(MAC地址),通过这样的ARP请求和响应,目的设备和源设备都会知道双方的IP地址和物理地址,并各自将这些IP地址和对应的物理地址记录下来,形成ARP条目表;
2、ARP报文格式
2.1:ARP协议共28字节(IPv4协议);
2.2:报文中主要提供:数据链路层的硬件类型(以太网)+协议类型(IPv4)+硬件地址和协议地址长度+操作码(请求或者应答)+目标设备和源设备的物理地址(MAC地址)和协议地址(IPv4);
3、ARP解析缓存
3.1:运行在设备中的程序会维护一个IP地址和MAC地址的对应关系表(ARP条目表),当发送设备需要解析IP地址时,去条目表中字节查找,c语言中,我们用结构体数组来实现ARP条目标;
3.2:ARP条目中的表项必须在一定的时间内更新,重新建立对应关系,比如主机更换IP地址、设备跟换网卡、主机关机、设备移除网络等,这些情况下,条目中将不再继续维护对应关系;
4、ARP实现例程
4.1:初始化ARP表
定义ARP条目表结构体
/*ARP条目结构体定义*/struct arp_entry{char proaddr[4]; //协议地址,我们使用IPV4地址 char mac_address[6]; //以太网的mac地址,即物理地址 char state; //arp条目状态 unsigned int time_out; //arp条目超时时间,指示条目何时更新char retry_cnts; //发送ARP请求,得不到回应时,重新发送ARP请求的次数 char usage_cnts; //条目被请求的次数};初始化ARP条目表,启动定时器
void arp_init(void)
{char i = 0;for(i=0;i<ARP_ENTRY_SIZE;i++){arp_cache[i].state = ARP_ENTRY_FREE;}/*开启定时器*/timer_start(&timer_arp,10);}
4.2:定义ARP报文结构体
/*arp报文结构体定义*/#pragma pack(1)struct arp_message{ unsigned short hwtype; //硬件类型 1:10Mbps以太网 unsigned short protype; //协议类型,第三层的协议类型,IPv4:0x0800 char hwaddrlen; //硬件地址长度,以太网:mac地址为6字节 char proaddrlen; //协议地址长度 IPv4:4字节 unsigned short opcode; //操作码 1:ARP请求 2:ARP应答 char sendhwaddr[6]; //发送者硬件地址 mac地址 char sendproaddr[4]; //发送者IP地址 char deshwaddr[6]; //目标硬件地址 mac地址 char desproaddr[4]; //目标协议地址 IP地址};#pragma pack()
4.2:处理ARP报文
(1)当数据链路层收到一个含有ARP模块的数据帧时,arp_process()函数被调用;
(2)在串口控制台上将受到的ARP报文进行打印;
(3)更新ARP条目表,受到的ARP数据包是ARP请求或者ARP响应报文,ARP请求数据包是局域网中的其他设备发送的以太网广播帧,不判断此数据包是不是给自己的,一并接受更新ARP条目;ARP响应数据包,肯定是本机设备发送的ARP请求,然后目标设备收到请求后做出的回应,也进行接受更新;
(4)判断接受到的数据是不是ARP请求并且判断ARP数据包是不是给自己的,如果是,发送ARP响应,告诉请求设备自己的MAC地址,请求设备会受到数据包问,并且更新ARP条目表;
void arp_process(void){//char i = 0;#ifdef debug_arparp_printf(); //在控制台上打印arp报文#endifarp_update(); //更新ARP条目 arp_entry_ptintf();/*判断是都是给自己的包*/if(memcmp(RX_ARP->desproaddr,IP,4) == 0){if(RX_ARP->opcode == HTONS(1)) /*判断是不是ARP请求*/{arp_respond(); /*发送arp响应*/ }}}APR更新函数,arp_process(),代码如下:
/*arp条目表更新*/void arp_update(void){char i = 0,j=0,cnt = 0;struct arp_entry *entry;for(i=0;i<ARP_ENTRY_SIZE;i++){entry = &arp_cache[i];if(entry->state == ARP_ENTRY_FREE)continue;if(memcmp(entry->proaddr,RX_ARP->sendproaddr,4) == 0) /*如果发现ARP条目中有接受到的IP地址,更新这个条目*/{memcpy(entry->mac_address,RX_ARP->sendhwaddr,6);entry->state = ARP_ENTRY_OK;entry->retry_cnts = ARP_RETRY_CNTS;entry->time_out = ARP_TIME_OUT;entry->usage_cnts = 0;return ;}}/*ARP条目中没有找到接受到的IP地址对应的条目*/for(i=0;i<ARP_ENTRY_SIZE;i++){entry = &arp_cache[i];if(entry->state == ARP_ENTRY_FREE){memcpy(entry->mac_address,RX_ARP->sendhwaddr,6);memcpy(entry->proaddr,RX_ARP->sendproaddr,4);entry->state = ARP_ENTRY_OK;entry->retry_cnts = ARP_RETRY_CNTS;entry->time_out = ARP_TIME_OUT;entry->usage_cnts = 0;return ;}}/*条目全满,依据条目被使用的次数来决定是否删除此条目*/ cnt = arp_cache[0].usage_cnts;for(i=1;i<ARP_ENTRY_SIZE;i++) /*找到使用次数最少的条目,然后更新值*/{entry = &arp_cache[i];if(entry->usage_cnts < cnt){cnt = entry->usage_cnts;j = i;}}entry = &arp_cache[j];memcpy(entry->mac_address,RX_ARP->sendhwaddr,6);memcpy(entry->proaddr,RX_ARP->sendproaddr,4);entry->state = ARP_ENTRY_OK;entry->retry_cnts = ARP_RETRY_CNTS;entry->time_out = ARP_TIME_OUT;entry->usage_cnts = 0;return ;}ARP响应函数,arp_respond(),代码如下:
/*发送arp响应*/void arp_respond(void){/*构建ARP响应报文*/generate_arp_messsage(0x0002,RX_ARP->sendproaddr,RX_ARP->sendhwaddr);/*构建以太网首部*/ generate_eth_head(RX_ARP->sendhwaddr,ARP_PROTOCOL);/*发送数据包*/ethernet_send(42); }
4.3:IP地址解析
(1)在串口控制台中输入IP地址,模拟IP地址解析,调用arp_ip_analyze()函数;
(2)判断ARP条目表中对否有IP对应的物理地址,如果有,将其打印至串口控制台;
(3)如果找不到,发送ARP请求,后会受到此条请求的响应ARP报文,然后更新ARP条目;
/*IP解析*/void arp_ip_analyze(char *ip_address){char i = 0;struct arp_entry *entry; for(i=0;i<ARP_ENTRY_SIZE;i++) /*检查entry条目中是否有IP对应的硬件地址*/{entry = &arp_cache[i];if(entry->state == ARP_ENTRY_FREE)continue;if(memcmp(entry->proaddr,ip_address,6) == 0){printf("IP %d.%d.%d.%d is found\r\n",ip_address[0],ip_address[1],ip_address[2],ip_address[3]);return;}}printf("IP %d.%d.%d.%d is not found\r\n",ip_address[0],ip_address[1],ip_address[2],ip_address[3]);/*entry条目中未找到对应的IP地址,发送ARP请求*/arp_request(ip_address);}
arp_request()函数,发送一个包含有本设备IP地址和mac地址的以太网广播帧,代码如下:
/*发送arp请求*/void arp_request(char *ip_address){char board_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};char mac[6] = {0,0,0,0,0,0}; /*arp请求中目的mac地址为0*/ /*构建ARP响应报文*/generate_arp_messsage(0x0001,ip_address,mac);/*构建以太网首部*/ generate_eth_head(board_addr,ARP_PROTOCOL);/*发送数据包*/ethernet_send(42); }
5:总结
使用PING指令,PING本机的ip地址,本机会收到ARP请求包,更新ARP条目表,然后发送ARP响应,然后查看电脑的ARP条目表,其中有记录设备的IP地址和MAC地址,设备的条目表中也出现电脑端的IP和MAC地址;
本例程使用内核时钟定时器进行arp条目的更新,由于时间关系,没有实现维护ARP表的函数,大概的思路是:
(1)sysclk是100ms中断一次,我们设定定时器的初始值为10,然后1s后定时器溢出,溢出后重新启动定时器,然后去arp条目里面找非空闲条目,对time_out减1,初始值为100,当time_out至0时,发送ARP请求,将此条目的state设置为ARP_ENTRY_RESOLVIN,表示此条目在等待回应;
(2)如果有回应,条目被更新,如果一直没有回应,维护表函数中将对retry_cnts定时减去1,retry_cnts至0后,还是没有回应,删除条目;
- 地址解析协议——ARP
- ARP——地址解析协议
- ARP:地址解析协议
- ARP:地址解析协议
- 地址解析协议(ARP)
- ARP地址解析协议
- ARP:地址解析协议
- ARP:地址解析协议
- 地址解析协议 ARP
- 地址解析协议(ARP)
- ARP地址解析协议
- ARP:地址解析协议
- arp(地址解析协议)
- ARP:地址解析协议
- 地址解析协议(ARP)
- arp 地址解析协议
- ARP地址解析协议
- ARP:地址解析协议
- 2.浅谈数据分析 数据分析报告
- JVM 类加载过程
- UVa10817 Headmaster's headache[状压DP]
- JS简单常用代码记录总结
- 进击的巨人(2017秋招总结)
- ARP——地址解析协议
- QToolButton按钮背景图片修改
- 用python 读取和写入CSV格式的文件
- AngularJS入门(10)-Angular服务总结
- Zookeeper-Zookeeper可以干什么
- 用angularJS的路由实现页面的跳转并传参
- Adapter汇总(ArrayAdapter,SimpleAdapter,BaseAdapter 简单入门)
- 嵌入式linux(TQ2440开发板)传输文件tftp服务器配置
- play框架用起来(1)