从0到1用java再造tcpip协议栈:代码实现ping应用功能1

2024-04-30 22:08

本文主要是介绍从0到1用java再造tcpip协议栈:代码实现ping应用功能1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

1.png

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

package protocol;import java.util.HashMap;public interface IProtocol {public byte[] createHeader(HashMap<String, byte[]> 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;@Overridepublic byte[] createHeader(HashMap<String, Object> 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<IProtocol> protocol_header_list = new ArrayList<IProtocol>();public ICMPProtocolLayer() {//添加错误消息处理对象error_handler_list.add(new ICMPUnReachableMsgHandler());//增加icmp echo 协议包头创建对象protocol_header_list.add(new ICMPEchoHeader());}
....public byte[] createHeader(HashMap<String, Object> 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;@Overridepublic byte[] createHeader(HashMap<String, Object> 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<IApplication> application_list = new ArrayList<IApplication>();@Overridepublic 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;}}

在下一小节,我们会继续完善代码。

更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
这里写图片描述

这篇关于从0到1用java再造tcpip协议栈:代码实现ping应用功能1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950044

相关文章

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri