以太网通讯
在计算机网络中,数据发送的过程就是把数据按照各层协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。
以太网包格式
目的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("!"); printf("MAC is "); for(i = 0; i < MAC_LENGTH; i++){ printf("%02X:", eh_addr[i]); } printf("! "); }