文章目录
1、构建ARP协议请求
在前面小节我们知道了ARP协议的请求/应答是28字节的,如下图所示,
那么实现ARP协议就是用代码在请求和接收时填充这28个字节,然后在再这28字节基础上添加以太网头部,就可以使用数据链路层的发送数据函数把ARP请求发送出去,下面一步一步做这件事情,
1.1、定义IProtocol接口
首先我们先定义一个接口IProtocol,这个接口中有两个方法,createHeader是封装请求数据帧,handlePacket是处理接收的数据帧。实现协议要实现这个接口。
public interface IProtocol {
public byte[] createHeader(HashMap<String, Object> headerInfo);
public HashMap<String, Object> handlePacket(Packet packet);
}
1.2、创建ARPProtocolLayer,实现IProtocol接口
首先创建APR协议层类ARPProtocolLayer,实现接口IProtocol。再createHeader方法中我们主要使用makeARPRequestMsg方法来实现对ARP请求数据帧的封装,makeARPRequestMsg方法需要我们传入目标IP地址,
public class ARPProtocolLayer implements IProtocol{
/*
* 数据包含数据链路层包头:dest_mac(6byte) + source_mac(6byte) + frame_type(2byte)
* 因此读取ARP数据时需要跳过开头14字节
*/
private static int ARP_OPCODE_START = 20;
private static int ARP_SENDER_MAC_START = 22;
private static int ARP_SENDER_IP_START = 28;
private static int ARP_TARGET_IP_START = 38;
private boolean analyzeARPMessage(byte[] data, HashMap<String, Object> infoTable) {
/*
* 解析获得的APR消息包,从中获得各项信息,此处默认返回的mac地址长度都是6
*/
//先读取2,3字节,获取消息操作码,确定它是ARP回复信息
byte[] opcode = new byte[2];
System.arraycopy(data, ARP_OPCODE_START, opcode, 0, 2);
//转换为小端字节序
short op = ByteBuffer.wrap(opcode).getShort();
if (op != ARPPacket.ARP_REPLY) {
return false;
}
//获取接受者ip,确定该数据包是回复给我们的
byte[] ip = DataLinkLayer.getInstance().deviceIPAddress();
for (int i = 0; i < 4; i++) {
if (ip[i] != data[ARP_TARGET_IP_START + i]) {
return false;
}
}
//获取发送者IP
byte[] senderIP = new byte[4];
System.arraycopy(data, ARP_SENDER_IP_START, senderIP, 0, 4);
//获取发送者mac地址
byte[] senderMac = new byte[6];
System.arraycopy(data, ARP_SENDER_MAC_START, senderMac, 0, 6);
infoTable.put("sender_mac", senderMac);
infoTable.put("sender_ip", senderIP);
return true;
}
private byte[] makeARPRequestMsg(byte[] ip) {
if (ip == null) {
return null;
}
DataLinkLayer dataLinkInstance = DataLinkLayer.getInstance(