300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > java 实现根据ip重定向_从0到1用java再造tcpip协议栈:代码实现ping应用功能1

java 实现根据ip重定向_从0到1用java再造tcpip协议栈:代码实现ping应用功能1

时间:2022-01-28 05:04:50

相关推荐

java 实现根据ip重定向_从0到1用java再造tcpip协议栈:代码实现ping应用功能1

上一节我们讲解了基于ICMP echo协议的ping原理,并提出下图的代码实现架构:

我们将遵照上面架构实现代码,首先为protocol后面的所有协议对象增加一个接口:

package protocol;

import java.util.HashMap;

public interface IProtocol {

public byte[] createHeader(HashMap headerInfo);

}

package protocol;

public class ProtocolManager {

private static ProtocolManager instance = null;

private ProtocolManager() {}

public static ProtocolManager getInstance() {

if (instance == null) {

instance = new ProtocolManager();

}

return instance;

}

public IProtocol getProtocol(String name) {

switch (name.toLowerCase()) {

case "icmp":

return new ICMPProtocolLayer();

case "ip":

return new IPProtocolLayer();

}

return null;

}

}

所有协议对象必须继承上面接口,处于Application处的应用对象直接调用协议对象该接口来封装发送数据包所需要的包头。接下来我们使用一个类专门用于构造协议头:

package protocol;

import java.nio.ByteBuffer;

import java.util.HashMap;

import java.util.Random;

import utils.Utility;

public class ICMPEchoHeader implements IProtocol{

private static int ICMP_EOCH_HEADER_LENGTH = 16;

private static short ICMP_ECHO_TYPE = 8;

private static short ICMP_ECHO_REPLY_TYPE = 0;

@Override

public byte[] createHeader(HashMap headerInfo) {

String headerName = (String)headerInfo.get("header");

if (headerName != "echo" && headerName != "echo_reply") {

return null;

}

byte[] buffer = new byte[ICMP_EOCH_HEADER_LENGTH];

ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);

short type = ICMP_ECHO_TYPE;

if (headerName == "echo_reply") {

type = ICMP_ECHO_REPLY_TYPE;

}

byteBuffer.putShort(type);

short code = 0;

byteBuffer.putShort(code);

short checkSum = 0;

byteBuffer.putShort(checkSum);

short identifier = 0;

if (headerInfo.get("identifier") == null) {

Random ran = new Random();

identifier = (short) ran.nextInt();

headerInfo.put("identifier", identifier);

}

identifier = (short) headerInfo.get("identifier");

byteBuffer.putShort(identifier);

short sequenceNumber = 0;

if (headerInfo.get("sequence_number") != null) {

sequenceNumber = (short) headerInfo.get("sequence_number");

sequenceNumber += 1;

}

headerInfo.put("sequence_number", sequenceNumber);

byteBuffer.putShort(sequenceNumber);

checkSum = (short) Utility.checksum(byteBuffer.array(), byteBuffer.array().length);

byteBuffer.putShort(4, checkSum);

return byteBuffer.array();

}

}

在ICMPProtocolLayer类中,我们依旧使用责任链模式调用相应对象来构造不同的包头:

public class ICMPProtocolLayer implements PacketReceiver, IProtocol{

....

private ArrayList protocol_header_list = new ArrayList();

public ICMPProtocolLayer() {

//添加错误消息处理对象

error_handler_list.add(new ICMPUnReachableMsgHandler());

//增加icmp echo 协议包头创建对象

protocol_header_list.add(new ICMPEchoHeader());

}

....

public byte[] createHeader(HashMap headerInfo) {

for (int i = 0; i < protocol_header_list.size(); i++) {

byte[] buff = protocol_header_list.get(i).createHeader(headerInfo);

if (buff != null) {

return buff;

}

}

return null;

}

}

由于发送ICMP echo数据包依然需要IP包头,因此我们先构建一个产生IP包头的类:

package protocol;

import java.nio.ByteBuffer;

import java.util.HashMap;

import utils.Utility;

public class IPProtocolLayer implements IProtocol{

private static byte IP_VERSION = 4;

private static int CHECKSUM_OFFSET = 10;

@Override

public byte[] createHeader(HashMap headerInfo) {

byte version = IP_VERSION;

byte internetHeaderLength = 5;

if (headerInfo.get("internet_header_length") != null) {

internetHeaderLength = (byte)headerInfo.get("internet_header_length");

}

byte[] buffer = new byte[internetHeaderLength];

ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);

byteBuffer.put((byte) (internetHeaderLength << 4 | version));

byte dscp = 0;

if (headerInfo.get("dscp") != null) {

dscp = (byte)headerInfo.get("dscp");

}

byte ecn = 0;

if (headerInfo.get("ecn") != null) {

ecn = (byte)headerInfo.get("ecn");

}

byteBuffer.put((byte)(dscp | ecn << 6));

if (headerInfo.get("total_length") == null) {

return null;

}

short totalLength = (short)headerInfo.get("total_length");

byteBuffer.putShort(totalLength);

int identification = 0;

if (headerInfo.get("identification") != null) {

identification = (int)headerInfo.get("identification");

}

byteBuffer.putInt(identification);

short flagAndOffset = 0;

if (headerInfo.get("flag") != null) {

flagAndOffset = (short)headerInfo.get("flag");

}

if (headerInfo.get("fragment_offset") != null) {

flagAndOffset |= ((short)headerInfo.get("fragment_offset")) << 3;

}

byteBuffer.putShort(flagAndOffset);

short timeToLive = 64;

if (headerInfo.get("time_to_live") != null) {

timeToLive = (short)headerInfo.get("time_to_live");

}

byteBuffer.putShort(timeToLive);

short protocol = 0;

if (headerInfo.get("protocol") == null) {

return null;

}

protocol = (short)headerInfo.get("protocol");

byteBuffer.putShort(protocol);

short checkSum = 0;

byteBuffer.putShort(checkSum);

int srcIP = 0;

if (headerInfo.get("source_ip") == null) {

return null;

}

srcIP = (int)headerInfo.get("source_ip");

byteBuffer.putInt(srcIP);

int destIP = 0;

if (headerInfo.get("destination_ip") == null) {

return null;

}

byteBuffer.putInt(destIP);

if (headerInfo.get("options") != null) {

byte[] options = (byte[])headerInfo.get("options");

byteBuffer.put(options);

}

checkSum = (short) Utility.checksum(byteBuffer.array(), byteBuffer.array().length);

byteBuffer.putShort(CHECKSUM_OFFSET, checkSum);

return byteBuffer.array();

}

}

接着我们构造应用程序管理对象,它将用于管理各个应用程序:

package Application;

public interface IApplication {

public int getPort();

public boolean isClosed();

public void handleData(byte[] data);

}

package Application;

public interface IApplicationManager {

public IApplication getApplicationByPort(int port);

}

package Application;

import java.util.ArrayList;

public class ApplicationManager implements IApplicationManager{

private ArrayList application_list = new ArrayList();

@Override

public IApplication getApplicationByPort(int port) {

for (int i = 0; i < application_list.size(); i++) {

IApplication app = application_list.get(i);

if (app.getPort() == port) {

return app;

}

}

return null;

}

}

在下一小节,我们会继续完善代码。更多经常内容请点击‘阅读原文’。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。