地址转换协议ARP

  在以太网协议中规定,同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的MAC地址。而在TCP/IP协议中,网络层和传输层只关心目标主机的IP地址。这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。于是需要一种方法,根据目的主机的IP地址,获得其MAC地址。这就是ARP协议要做的事情。

  所谓地址解析(address resolution)就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。

理论结构

  ARP软件可分为三部分:

  • 输出模块

    • 将高层协议地址与相应的物理地址进行绑定,返回给网络接口程序
  • 输入模块
    • 处理来自网络的ARP分组,并通过增加新的绑定来修改ARP高速缓存的内容
  • 高速缓存管理程序
    • 实现高速缓存替换策略;检测高速缓存中的所有表项,删除已达到规定时限的表项

输出模块

  该模块主要是要接收IP数组请求,然后查找物理地址,返回。

  主要步骤为:

  1. 睡眠,直到IP软件收到IP分组。

  2. 检查高速缓存表,寻找对应于这个IP分组的项目。

  3. if ( 找到 ){

      if ( 状态为 RESOLVED ){

        提取硬件物理地址;

        将分组连同硬件物理地址一起发送到数据链路层;

return;

      }

      else if ( 状态为 PENDING ){

       将分组放入相应的队列;

   return;

     }

    }

    else{

      创建一个队列;

      将分组加入到队列中;

      创建一个高速缓存项目,状态设置为 PENDING ,ATTEMPTS 为 1;

      发送ARP请求;

    }

ARP高速缓存队列

  它是用数组来存储的。

extern struct arpentry arptable[ARP_TSIZE]

搜索ARP高速缓存

/* arpfind.c - arpfind */   

#include <conf.h>
#include <kernel.h>
#include <network.h> /*------------------------------------------------------------------------
* arpfind - find an ARP entry given a protocol address and interface
*------------------------------------------------------------------------
*/
struct arpentry *
arpfind(u_char *pra, u_short prtype, struct netif *pni)
{
struct arpentry *pae; /* 定义ARP缓存结构体指针 */
int i; for (i=; i<ARP_TSIZE; ++i) { /* 遍历ARP高速缓存 */
pae = &arptable[i]; /* 高速缓存数组 */
if (pae->ae_state == AS_FREE) /* 缓存为空闲接找下一个 */
continue;
if (pae->ae_prtype == prtype && /* 协议类型相同 */
pae->ae_pni == pni && /* 接口和协议地址相同 */
BLKEQU(pae->ae_pra, pra, pae->ae_prlen)) /* BLKEQU的定义 #define BLKEQU(b1, b2, len) (!memcmp((b1), (b2), len))*/
return pae;
}
return ;
}

ARP请求分组的广播

/* arpsend.c - arpsend */

#include <conf.h>
#include <kernel.h>
#include <network.h> /*------------------------------------------------------------------------
* arpsend - broadcast an ARP request
* N.B. Assumes interrupts disabled
*------------------------------------------------------------------------
*/
int arpsend(pae)
struct arpentry *pae; //指向高速缓存的表项
{
struct netif *pni = pae->ae_pni;
struct ep *pep;
struct arp *parp;
int arplen; pep = (struct ep *) getbuf(Net.netpool); //生成ARP请求分组
if ((int)pep == SYSERR)
return SYSERR;
blkcopy(pep->ep_dst, pni->ni_hwb.ha_addr, pae->ae_hwlen);
pep->ep_type = EPT_ARP;
pep->ep_order = EPO_NET;
parp = (struct arp *) pep->ep_data;
parp->ar_hwtype = hs2net(pae->ae_hwtype);
parp->ar_prtype = hs2net(pae->ae_prtype);
parp->ar_hwlen = pae->ae_hwlen;
parp->ar_prlen = pae->ae_prlen;
parp->ar_op = hs2net(AR_REQUEST);
blkcopy(SHA(parp), pni->ni_hwa.ha_addr, pae->ae_hwlen);
blkcopy(SPA(parp), &pni->ni_ip, pae->ae_prlen);
bzero(THA(parp), pae->ae_hwlen);
blkcopy(TPA(parp), pae->ae_pra, pae->ae_prlen);
arplen = ARP_HLEN + *(parp->ar_hwlen + parp->ar_prlen);
write(pni->ni_dev, pep, EP_HLEN+arplen); //发送请求分组
return OK;
}

输入模块

   从一个队列中拿走一个分组,并连同解析出的物理地址一起发送给数据报链路层传输。

  主要步骤为

  1. 睡眠,直到ARP分组到达(请求或回答)。

  2. 检查高速缓存表,寻找对应这个ARP分组的项目。

  3. if ( 找到 ){

     if ( 状态是 RESOLVED ){

      更新项目;

      return;

     }

     else if ( 状态是 PENDING ){

      更新项目;

如果队列非空的话,将一个分组从队列中取出,将它与硬件地址一起发送给数据链路层;

      return;

     {

    }

    else{

    创建一个项目;

    将此项目添加到表中;

    return;

    }

  4.  如果分组是一个请求, 发送ARP回答。

向表中增加已转换的表项

/* arpadd.c - arpadd */

#include <conf.h>
#include <kernel.h>
#include <network.h> struct arpentry *arpalloc(void); /*------------------------------------------------------------------------
* arpadd - Add a RESOLVED entry to the ARP cache
* N.B. Assumes interrupts disabled
*------------------------------------------------------------------------
*/
struct arpentry *
arpadd(struct netif *pni, struct arp *parp)
{
struct arpentry *pae; pae = arpalloc(); //在高速缓存中分配一个表项 /* 利用ARP分组信息填写表项 */
pae->ae_hwtype = parp->ar_hwtype;
pae->ae_prtype = parp->ar_prtype;
pae->ae_hwlen = parp->ar_hwlen;
pae->ae_prlen = parp->ar_prlen;
pae->ae_pni = pni;
pae->ae_queue = EMPTY;
memcpy(pae->ae_hwa, SHA(parp), parp->ar_hwlen);
memcpy(pae->ae_pra, SPA(parp), parp->ar_prlen);
/* 初始化 */
pae->ae_ttl = ARP_TIMEOUT;
pae->ae_state = AS_RESOLVED;
return pae;
}

发送等待发送的分组

/* arpqsend.c - arpqsend */

#include <conf.h>
#include <kernel.h>
#include <network.h> int netwrite(struct netif *, struct ep *, unsigned); /*------------------------------------------------------------------------
* arpqsend - write packets queued waiting for an ARP resolution
*------------------------------------------------------------------------
*/
void
arpqsend(struct arpentry *pae)
{
struct ep *pep;
struct netif *pni; if (pae->ae_queue == EMPTY)
return; pni = pae->ae_pni;
/* 遍历等待发送的分组队列,调用netwrite逐个放入网络输出队列中 */
while (pep = (struct ep *)deq(pae->ae_queue))
netwrite(pni, pep, pep->ep_len);
freeq(pae->ae_queue); //队列为空后,释放自身
pae->ae_queue = EMPTY;
}

高速缓存管理

  高速缓存是用来存储IP地址与物理地址的。如果一个IP进行需要发送一个数据报,但其目的地址不在ARP高速缓存中,就会创建一个新的表项,然后广播相应的请求分组,并等待分组置入队列中。

  主要步骤:

1. 睡眠,周期性的唤醒。

2. 遍历高速缓存的每一个项目:

  if ( 状态为FREE )

continue;

if ( 状态为PENDING ){

    尝试次数+1;

    if ( 尝试次数达到最大次数 ){

      该项目状态->FREE;

    撤销相应的队列;

    }

    else {

      发送ARP请求;

    }

    continue;

  }

  else if( 状态为RESOLVED ){

    将超时字段的值减去已经过去的时间;

    若结果小于0,状态->FREE,撤销相应队列。

  }

 替换策略

/* arpalloc.c - arpalloc */   

#include <conf.h>
#include <kernel.h>
#include <proc.h>
#include <network.h> void arpdq(struct arpentry *); /*------------------------------------------------------------------------
* arpalloc - allocate an entry in the ARP table
* N.B. Assumes interrupts DISABLED
*------------------------------------------------------------------------
*/
struct arpentry *arpalloc()
{
static int aenext = ; //静态变量,保证循环
struct arpentry *pae;
int i; for (i=; i<ARP_TSIZE; ++i) { //遍历表
if (arptable[aenext].ae_state == AS_FREE)
break;
aenext = (aenext + ) % ARP_TSIZE; //循环替换
}
pae = & arptable[aenext];
aenext = (aenext + ) % ARP_TSIZE; if (pae->ae_state == AS_PENDING && pae->ae_queue >= )
arpdq(pae);
pae->ae_state = AS_PENDING;
return pae;
}

地址转换协议ARP的更多相关文章

  1. RARP反向地址转换协议

    反向地址转换协议(RARP:Reverse Address Resolution Protocol) 反向地址转换协议(RARP)允许局域网的物理机器从网关服务器的 ARP 表或者缓存上请求其 IP ...

  2. 【原创】锐捷实现OSPF路由协议和NAT地址转换协议

    路由网络设计与实施 [锐捷设备实现OSPF路由协议与NAT地址转换] 说明:   本文是在多VLAN双星型交换网络的基础之上发展的.关于组建多VLAN双星型交换网络,请参阅: <思科和锐捷组建多 ...

  3. 【RL-TCPnet网络教程】第23章 RL-TCPnet之地址解析协议ARP

    第23章      RL-TCPnet之地址解析协议ARP 本章节为大家讲解ARP(Address Resolution Protocol,地址解析协议),通过前面章节对TCP和UDP的学习,需要大家 ...

  4. 2016.7.8 计算机网络复习要点第四章之地址解析协议ARP

    1.地址解析协议ARP:知道一个机器的IP地址,需要找到其相应的硬件地址:ARP协议的用途是为了从网络层使用的IP地址解析出在链路层使用的硬件地址: 2.由于是IP协议使用了ARP协议,因此通常就把A ...

  5. 四、IP地址转换

    IP地址与端口 TCP/IP(传输控制协议/网际协议)不是一个协议,而是一组协议的总称,包括IP.TCP.UDP.ICMP.ARP等.它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据 ...

  6. <TCP/IP>地址解析协议ARP

    从前两章中有学到,网络层地址和链路层地址是由不同的,一个是物理地址,一个是IP地址.物理地址固定存储在网卡中,不会改变,而IP地址是可以网络管理员和用户自己分配的 在传统的IPv4网络中,一台A主机要 ...

  7. TCP/IP具体解释学习笔记——地址解析协议ARP

    一 概述 我们知道,IP协议是用来在不同的物理网络之间数据传输的.要在不同的网络之间数据传输,至少须要将IP协议所用的地址转换成特定网络所使用的物理地址. 一般来说.就是将IPv4地址转换为mac地址 ...

  8. 地址解析协议ARP与逆地址解析协议RARP

    IP地址是用来通信的,但是和硬件地址是有区别的.物理地址是数据链路层和物理层使用的地址,IP地址是网络层及以上各层使用的地址. 发送数据时,数据从高层向下层传输,使用IP地址的IP数据报交给下层的数据 ...

  9. Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)

    IPv4套接字地址结构 struct sockaddr_in { uint8_t sinlen;(4个字节) sa_family_t sin_family;(4个字节) in_port_t sin_p ...

随机推荐

  1. HDOJ(1010)DFS+剪枝

    Tempter of the Bone http://acm.hdu.edu.cn/showproblem.php?pid=1010 #include <stdio.h> #include ...

  2. B-F 字符串匹配算法

    Brute-Froce 算法是串的匹配模式算法中的一种其匹配方式如下: 1.设有字符串 a ,b;a为主串,在 a 中查找 b 串的位置 2.匹配方式如下: 2.1: 分别从 a,b串的第一个元素开始 ...

  3. Mysql常用命令行大全——转载

    转载地址:http://www.blogjava.net/supperchen/archive/2012/10/11/389340.html 第一招.mysql服务的启动和停止 net stop my ...

  4. jqeury datatable

    1.自定义列信息    "aoColumnDefs":[                               {                               ...

  5. jquery动态创建页面元素

    jquery用$()方法动态创建一个页面元素,例如: var $div=$("<div title='动态创建页面元素'>欢迎创建一个新的div</div>" ...

  6. The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决

    问题 The certificate used to sign "AppName" has either expired or has been revoked. An updat ...

  7. 使用C# WinForm制作 员工打卡项目 -- S2 2.3

    新建一个员工类,存储员工的信息 新建一个List<>集合,并在load事件中实例化三个员工对象 DataGridView绑定数据源,可以显示出数据 点击查询按钮,查询工号等同于输入的数的员 ...

  8. iOS应用之微信支付集成-直接前端集成

    所有信息的生成都在前端完成,包括对订单进行sign签名以及MD5签名加密(此方法相对来说有些复杂,没有官方给的方法简单).注:官方给的是v3&v4支付流程,签名和加密都是在服务器端进行,由于没 ...

  9. Asp.net Session 保存到MySql中

    一 网站项目引入"mysql.web.dll" 二 web.config配置中添加mysql数据库连接字符串 <connectionStrings> <remov ...

  10. JS打印页面

         打印 整个html页面(PS:样式要写在页面里面才能打印(就是用内部样式))             <a id="dayi" runat="server ...