以太网通讯
在计算机网络中,数据发送的过程就是把数据按照各层协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。
以太网包格式
目的MAC地址:接收者的物理地址(6字节)
源MAC地址:发送者的物理地址(6字节)
类型:高层数据使用的协议类型(2字节)
数据:高层的数据(46~1500字节)
CRC:校验码(4字节)
ARP功能
在以太网络中,每一台计算机的唯一身份表示是MAC地址(物理层的地址),两台计算机要进行通讯,必须要知道对方的MAC地址,但是用户通常只知道对方的IP地址 ,这时就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包并且满足条件的计算机会恢复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址和MAC地址的协议。
ARP包格式
ARP包属于网络层,分为请求包和应答包,通过OP字段来区分。
以太网目的地址(6字节)
以太网源地址(6字节)
帧类型(2字节)
硬件类型(2字节)
协议类型(2字节)
硬件地址长度(1字节)
协议地址长度(1字节)
OP(2字节)
发送端以太网地址(6字节)
发送端到IP地址(4字节)
目的以太网地址(6字节)
目的IP地址(4字节)
网络字节序
在网络通讯中认为主机都是大端模式。对与多个字节的需要转换,一个字节的不用转换。
小端模式:低地址放低字节,高地址放高字节
大端模式:低地址方高字节,高地址放低字节
/********************************************************************
*名称:arp.c
*作者:D
*时间:2015.11.26
*功能:ARP协议
*********************************************************************/ /********************************************************************
*宏定义
*********************************************************************/
#define ETH_ARP 0x0806 //ARP
#define ETH_RARP 0x0805 //RARP
#define ARP_ETH 0x0001 //ETHERNET
#define ARP_IP 0x0800 //IP
#define ARP_REQ 0x0001 //Request
#define ARP_REP 0x0002 //Reply #define HTONS(n) ( (((n)&0xFF00)>>8) | (((n)&0x00FF)<<8) ) //把unsigned short类型从主机序转换到网络序 #define MAC_LENGTH 6 //MAC地址长度
#define IP_LENGTH 4 //IP地址长度
#define PACKET_LENGTH 42 //ARP报文包长度,以太网帧最小长度为64字节,发送时会自动填充为64字节 /********************************************************************
*类型定义
*********************************************************************/
//以太网帧首部
typedef struct ehhdr
{
unsigned char eh_dst[6]; //destination ethernet addrress
unsigned char eh_src[6]; //source ethernet addresss
unsigned short eh_type; //ethernet packet type
}EHHDR, *PEHHDR; //以太网帧数据
typedef struct arphdr
{
unsigned short arp_hrd; //format of hardware address
unsigned short arp_pro; //format of protocol address
unsigned char arp_hln; //length of hardware address
unsigned char arp_pln; //length of protocol address
unsigned short arp_op; //ARP/RARP operation unsigned char arp_sha[6]; //sender hardware address
unsigned char arp_spa[4]; //sender protocol address
unsigned char arp_tha[6]; //target hardware address
unsigned char arp_tpa[4]; //target protocol address
}ARPHDR, *PARPHDR; //ARP报文包
typedef struct arpPacket
{
EHHDR ehhdr;
ARPHDR arphdr;
}ARPPACKET, *PARPPACKET; /********************************************************************
*全局变量声明
*********************************************************************/
unsigned char eh_src[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; //MAC发送地址
unsigned char eh_dst[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //MAC目的地址 unsigned char ip_src[4] = {192, 168, 1, 150}; //IP发送地址
unsigned char ip_dst[4] = {192, 168, 1, 100}; //IP目的地址 /********************************************************************
*函数原型声明
*********************************************************************/
void requst_arp();
void create_packet(ARPPACKET *arp_packet); void process_arp(ARPPACKET *arp_packet); /********************************************************************
*名称:requst_arp
*参数:
* none
*返回:
* none
*功能:ARP请求
*********************************************************************/
void requst_arp(){
ARPPACKET arp_packet; //ARP报文包 //创建ARP报文包
create_packet(&arp_packet); //发送ARP报文包
tx_dm9000(&arp_packet, PACKET_LENGTH);
} /********************************************************************
*名称:create_packet
*参数:
* arp_packet 报文包
*返回:
* none
*功能:创建ARP报文包
*********************************************************************/
void create_packet(ARPPACKET *arp_packet){
//填充以太网帧首部
memcpy(arp_packet->ehhdr.eh_dst, eh_dst, MAC_LENGTH); //MAC目的地址
memcpy(arp_packet->ehhdr.eh_src, eh_src, MAC_LENGTH); //MAC发送地址
arp_packet->ehhdr.eh_type = HTONS(ETH_ARP); //帧类型 //填充以太网帧数据
arp_packet->arphdr.arp_hrd = HTONS(ARP_ETH); //硬件类型
arp_packet->arphdr.arp_pro = HTONS(ARP_IP); //协议类型
arp_packet->arphdr.arp_hln = MAC_LENGTH; //硬件地址长度
arp_packet->arphdr.arp_pln = IP_LENGTH; //协议地址长度
arp_packet->arphdr.arp_op = HTONS(ARP_REQ); //操作类型 memcpy(arp_packet->arphdr.arp_sha, eh_src, MAC_LENGTH); //MAC发送地址
memcpy(arp_packet->arphdr.arp_spa, ip_src, IP_LENGTH); //IP发送地址
memcpy(arp_packet->arphdr.arp_tha, eh_dst, MAC_LENGTH); //MAC目的地址
memcpy(arp_packet->arphdr.arp_tpa, ip_dst, IP_LENGTH); //IP目的地址
} /********************************************************************
*名称:process_arp
*参数:
* arp_packet 报文包
*返回:
* none
*功能:处理ARP报文包
*********************************************************************/
void process_arp(ARPPACKET *arp_packet){
int i;
unsigned char eh_addr[6]; //物理地址
unsigned char ip_addr[4]; //协议地址 //提取发送地址
memcpy(eh_addr, arp_packet->arphdr.arp_sha, MAC_LENGTH);
memcpy(ip_addr, arp_packet->arphdr.arp_spa, IP_LENGTH); //打印发送地址
printf("IP is ");
for(i = 0; i < IP_LENGTH; i++){
printf("%3d.", ip_addr[i]);
}
printf("\b!"); printf("MAC is ");
for(i = 0; i < MAC_LENGTH; i++){
printf("%02X:", eh_addr[i]);
}
printf("\b!\n");
}