当前位置: 首页 > news >正文

大二学生眼中的Netty?基于Netty实现内网穿透!

爷的开场白

掘金的朋友们大家好!我是新来的Java练习生 CodeCodeBond!

这段时间呢,博主在学习Netty,想做一个自己感兴趣好玩的东西,那就是内网穿透!!(已经实现主要代理功能但有待优化)

后面会介绍到我个人的一些思路(能把学校内网的电控系统穿出来玩玩嘿嘿嘿

老实求放过说明: 博主对Netty底层知识仅仅是了解一下皮毛,哈哈哈精巧的框架让像我这种黄毛小子短时间熟悉精通确实不是那么容易的,需要时间的沉淀(#沉淀 orz)

什么!连Netty的底层知识都不懂!居然还会用Netty做开发网络编程???我想这也是框架的意义所在吧!将复杂繁琐的底层封装成简单好用且高性能的API,让开发者快速上手。(大多数Java混子curdBoy不也不知道Spring框架, Mysql的底层么…os:真是自己骂自己)

简单聊聊我眼中Netty是什么

Netty是一个优雅著称的高性能网络编程框架, 用于快速开发可维护的高性能协议服务器和客户端。Netty被广泛应用于各类网络应用开发,尤其是需要高性能和低延迟的场景,如游戏服务器、各种中间件和分布式系统等等。

Netty在我的眼里, 是Java领域内高性能网络编程的基石。 在网络编程的地位非常之高,有多高呢,有三四百层楼那么高吧。

可能身边的同学们还在用各种RPC、MQ…ES的时候,还不知道Netty在里面吧!(一种精通…咳咳,了解Netty的快感油然而生~)

没错,我们熟知的Dubbo,grpc的java端,rocket mq等等底层都有Netty的相关实现。Spring的web相关组件也是大量用到Netty,比如webFlux等。足以说明Netty的地位。

我认为Netty有两大特点,异步和回调。这使得Netty在高并发下仍能保持良好的性能以及处理各种事件。

问题来了,不熟悉网络编程的我在一开始上手十分困难,异步的机制和回调的代码书写让我感到十分难受,后来越来越被这种特点着迷,实际上Netty异步回调的代码实现的非常优雅。

大量用到前人总结的设计模式,例如handler处理时候自定义的责任链模式,回调函数Listener的观察者模式… 真正的让开发者自由扩展,优雅编程。

下面我来简单说说Netty开发时的常用组件

常用组件

EventLoop(事件循环对象)

EventLoop 本质是一个单线程执行器,同时维护了一个Selector,里面有run方法处理Channel上源源不断地io事件。

它有两条继承线:

1、java并发包下的 j.u.c.ScheduledExecutorService 包含所有线程池的方法

2、Netty自身OrderedEventExecutor,

提供了 isEventLoop(Thread thread) 方法判断这个线程是否属于它

提供了parent方法 来看自己属于哪个EventLoopGroup

EventLoopGroup (事件循环组)

事件循环组

eventloopgroup是一组eventloop,channel一般会调用eventloopgroup的register方法来绑定其中一个

eventloop,后续这个(hannel 上的10事件都由此eventloop来处理(保证了io事件处理时的线程安全)

继承自 netty 自己的 ececutorgroup

实现了 iterable接口提供遍历 eventloop的 的能力

另有next 方法获取集合中下一个eventloop

ps: 其实一般开发就用两个,如果是接收多端的服务端ServerBootstrap那就一个BossGroup一个WorkerGroup,boss处理accept连接,而worker则处理io事件。如果是连接一个服务端的客户端,那么就只需要一个worker就可以啦

Channel

channel的主要作用及其常用函数

close()可以用来关闭channel

closefuture0用来处理channel的关闭

sync方法作用是同步等待channel关闭

而ad addlistener 方法是异步等待channel 关闭

pipeline()方法添加处理器,(自定义处理器,编解码处理器等等,Idle保活等等)

write()方法将数据写入

writeandflush0方法将数据写入并刷出

Future

搭配Promise既可以同步也可以异步,可以用的十分丰富炫酷,可以搭配juc去配套食用理解。

EmbeddedChannle

一般用来测试自己的处理器,很方便,可以直接将数据刷入站,读入站的数据。出站同理。

我就用来测试自己消息传输协议的编解码器,很方便的。

ByteBuf
  1. 池化与非池化, 减少建立连接的开销
  2. 直接内存与堆内存,直接内存读写快,堆内存分配快,相辅相成
  3. 自动扩容机制, 每次检测是否够空间()-> 不够 { 小于512直接扩容到512, 如果大于512都是*2处理 }

没错,仅需要这些组件(还有一些Handler要知道)就可以开始愉快的网络编程了。起飞~

我认为Netty能干嘛

掌握了这些,我能做什么。掌握了这些,你可以自由开发你能想到的网络编程,甚至是做一个服务器去代替Tomcat,咳咳(我相信有部分公司应该是不用tomcat的…吧)精通了Netty,那真的是非常之牛掰了,真正的掌握JUC、NIO、Socket编程的王Orz

比如能干嘛呢? 比如你可以基于Netty可以实现简单的聊天室功能了(被写烂了)参考某马程序员的Netty课程。如果要实现的比较正式高级的聊天室,可以到某站搜索程序员老罗, 他的仿微信项目中的聊天业务使用的Netty比较好!开源精神o( ̄▽ ̄)d;

我对内网穿透比较有兴趣,所以我学完Netty的基础后捏,就快速的上手手搓了一个简单的内网穿透项目,嗨嗨嗨!

(等我完善好哈,我一定要开源出来,做到简单配置,简单使用,简单扩展,覆盖大多数人的需求。/加油,xdm双击点波关注上车了喂)

我的内网穿透分析

下面是我实现内网穿透的思路, 有更好的思路欢迎讨论一起交流进步!

概括起来 其实主要分为三步:

1、 自定义消息传输协议 protocol。消息类包括type,data…当然还要有编解码器。

2、 监听访客端, 代理服务端, 代理客户端, 内网服务端。 四端以及他们的对应的自定义Handler。

3、 设计什么时候建立什么通道,什么时候用什么通道发送数据,什么时候关闭通道。并且如何维护这条通道,不会乱窜。

一、自定义消息传输协议

既然是协议,那肯定有消息体,有编解码。

首先ProxyMsg这个类你可以随便造,最简单的必须要有的也就是type和data,两个属性,其他消息流水号、指令消息等等可以自由发挥~ 这里是一个PeoxyMsg示例:

@Data
@EqualsAndHashCode
public class ProxyMsg {/** 心跳 */public static final byte TYPE_HEARTBEAT = 0x00;/** 数据传输 */public static final byte TYPE_TRANSFER = 0x01;/** 连接 */public static final byte TYPE_CONNECT = 0x10;/** 连接断开 */public static final byte TYPE_DISCONNECT = 0x11;//-----------------------------------------------------/** 消息类型 */private byte type;/** 消息携带数据 */private byte[] data;}

因为Netty是基于字节流的(ByteBuf)数据传输时自然会有粘包、半包的问题。所以编解码器要去解决这个问题。ProxyMsgEncoder和ProxyMsgDecoder。

如何去解决粘包问题呢? Netty提供了一个解决方案,使用LengthFieldBasedFrameDecoder实现定长解码器,通过定义一条消息的各部分的实际长度,控制解码读取字节的时候不多读,不少读,按照规定字段长度读!

这里提供同样,也提供一个ProxyMsgDecoder的示例哈:

@Slf4j
public class ProxyMsgDecoder extends LengthFieldBasedFrameDecoder {public ProxyMsgDecoder(){super(Integer.MAX_VALUE, 0, 4, 0, 0);}@Overrideprotected ProxyMsg decode(ChannelHandlerContext ctx, ByteBuf in2) throws Exception {ByteBuf in = (ByteBuf) super.decode(ctx, in2);log.info("in:{}",in);if(in==null||in.readableBytes()<4){return null;}int dataLen = in.readInt();byte type = in.readByte();ProxyMsg msg = new ProxyMsg();msg.setType(type);if(dataLen>1){byte[] data = new byte[dataLen - 1];in.readBytes(data);msg.setData(data);}
//        log.info("msg:{}",msg);in.release();return msg;}
}

既然消息的解码器你已经想好了,将ByteBuf进行编码成ProxyMsg就很简单了,这里是ProxyEncoder类示例:

@Slf4j
public class ProxyMsgEncoder extends MessageToByteEncoder<ProxyMsg> {//提供空参构造public ProxyMsgEncoder(){}@Overrideprotected void encode(ChannelHandlerContext ctx, ProxyMsg msg, ByteBuf out) throws Exception {
//        log.info("msg encode:{}",msg);int bodyLen = 1;  //一个字节表示类型长度嘛,这个必须有的if(msg.getData() != null){bodyLen += msg.getData().length;}//先写入消息体长度 单位字节out.writeInt(bodyLen);//写入消息体类型out.writeByte(msg.getType());//写入消息携带的dataif (msg.getData() != null) {out.writeBytes(msg.getData());}}
}

ok,这样就做好了最简单的消息协议了,是不是发现协议其实也就是一种约定罢了,但是真正的协议其实要复杂的多。这里就不赘述了 O.o

用刚刚说到的EmbeddedChannel来测试一下吧!

public class Test {public static void main(String[] args) {EmbeddedChannel channel = new EmbeddedChannel();ProxyMsg msg = new ProxyMsg();msg.setType(ProxyMsg.TYPE_HEARTBEAT);msg.setData("11111".getBytes());channel.pipeline().addLast(new ProxyMsgDecoder()).addLast(new ProxyMsgEncoder());channel.writeOutbound(msg);ByteBuf encodedMsg = channel.readOutbound();channel.writeInbound(encodedMsg);ProxyMsg decodedMsg = channel.readInbound();System.out.println("Type: " + decodedMsg.getType());System.out.println("Data: " + new String(decodedMsg.getData()));System.out.println(0x10);}
}

测试结果不出所料,没错,日志打出来的就是我们想要的嘛。

直到这里,我们真正的建立好了简单的消息传输协议,可以开始着手做Socket的开发了。

二、我选择设计四个Socket

我将按照访客 => 代理服务端 => 代理客户端 => 内网服务; 这样的顺序来讲
反之同理


首先我觉得有必要说一下启动的流程: 是
先把代理两端也就是Netty做的代理服务端和客户端启动并相连接,当客户端连接上服务端后建立一条,客户端Connect.addListener()发送一条TYPE_CONNECT的消息,服务端收到解析后,注册这条主通道

注册好主通道后,启动访客端,监听公网某某端口,接收访客的请求数据。当有访客连接,建立访客通道

启动内网服务端,connect.addListener()连接成功的话,就建立起内网服务真实通道。

因为Netty是异步的,每个启动中的步骤他都是一起执行的。所以这些操作只需要注意启动的顺序就可以了,代理服务器启动-> 代理客户端-> 内网服务端&&访客端启动

以下是实现的端口以及handler的分析

内网服务Socket\代理客户端 : Bootstrap

访客代理Socket\代理服务端 : ServerBootstrap

为什么呢? 其实判断他是单端的,还是多端的,就会明白!

  1. VisitorSocket&Handler 他会启动一个服务器并监听某个端口,用于给访客访问。当访客访问端口的时候,建立起一个访客通道,并发送访问请求的数据到ServerSocket(代理服务端);
  2. ServerSocket&Handler 启动代理服务端,根据消息类型的不同,处理消息的转发。当第一次和代理客户端相连接注册起主通道用来传输指令和唤起路由通道。
  3. ProxySocket&Handler 启动代理客户端,接收访客数据并解析转发给内网服务。
  4. ServiceSocket&Handler 启动内网服务端,新建一条路由通道发送CONNECT消息给代理服务端注册该通道。处理器对响应(Read到的)数据进行封装成TYPE_TRANSFER的消息,转发给代理服务端转发对应的访客通道。

四个Socket端,和对应四个Handler,和对应protocol协议,你数数加起来才几个类?
1234… 是的,也就才十一个类,再加一个server和client两个模块下的Constant,也才13个类就完成了Netty实现的内网穿透,是不是非常简单呢?

爷的结束语

最近期末周+准备投简历有点忙不过来,等我结束这段时间,我把内网穿透完善一下,在下篇文章我就开源出来,供大家使用、扩展自己需求。请xdm多多支持!感谢铁铁们。
凌晨一点半了,晚安各位Zzzzzzzzzzzzzzzzzzzzzzzzzzz

相关文章:

大二学生眼中的Netty?基于Netty实现内网穿透!

爷的开场白 掘金的朋友们大家好&#xff01;我是新来的Java练习生 CodeCodeBond&#xff01; 这段时间呢&#xff0c;博主在学习Netty&#xff0c;想做一个自己感兴趣好玩的东西&#xff0c;那就是内网穿透&#xff01;&#xff01;&#xff08;已经实现主要代理功能但有待优化…...

JavaStringBuffer与StringBuilder

StringBuffer、StringBuilder 文章目录 StringBuffer、StringBuilderStringBuffer和StringBuilder的理解可变性分析对于String对于StringBuilder 常用方法执行效率对比 StringBuffer和StringBuilder的理解 String 不可变的字符序列 StringBuffer 可变的字符序列 JDK1.0声明&…...

云徙科技助力竹叶青实现用户精细化运营,拉动全渠道销售额增长

竹叶青茶以其别具一格的风味与深厚的历史底蕴&#xff0c;一直被誉为茶中瑰宝。历经千年的传承与创新&#xff0c;竹叶青不仅坚守着茶叶品质的极致追求&#xff0c;更在数字化的浪潮中&#xff0c;率先打破传统&#xff0c;以科技力量赋能品牌&#xff0c;成为茶行业的领军者。…...

深度揭秘:深度学习框架下的神经网络架构进化

深度学习框架下的神经网络架构经历了从基础到复杂的显著进化&#xff0c;这一进程不仅推动了人工智能领域的突破性进展&#xff0c;还极大地影响了诸多行业应用。本文旨在深入浅出地揭示这一进化历程&#xff0c;探讨关键架构的创新点及其对现实世界的影响。 引言&#xff1a;…...

MySQL的DML语句

文章目录 ☃️概述☃️DML☃️添加数据☃️更新和删除数据☃️DML的重要性 ☃️概述 MySQL 通用语法分类 ● DDL: 数据定义语言&#xff0c;用来 定义数据库对象&#xff08;数据库、表、字段&#xff09; ● DML: 数据操作语言&#xff0c;用来对数据库表中的数据进行增删改 …...

Wireshark的基本用法以及注意事项

Wireshark 是一个流行的网络协议分析工具&#xff0c;可以捕获和分析网络数据包。以下是一些常见的 Wireshark 的用法&#xff1a; 安装和启动&#xff1a;首先需要下载和安装 Wireshark。安装完成后&#xff0c;可以通过启动 Wireshark 应用程序来打开它。 选择网络接口&…...

集团门户网站的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;集团文化管理&#xff0c;基础数据管理&#xff0c;公告通知管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;论坛&#xff0…...

Tomcat基础详解

第一篇&#xff1a;Tomcat基础篇 lecture&#xff1a;邓澎波 一、构建Tomcat源码环境 工欲善其事必先利其器&#xff0c;为了学好Tomcat源码&#xff0c;我们需要先在本地构建一个Tomcat的运行环境。 1.源码环境下载 源码有两种下载方式&#xff1a; 1.1 官网下载 https://…...

【Python爬虫】爬取名人名言页面并进行简单的数据清洗(入门级)

目录 资源链接 一、网站选择 二、数据爬取要求 三、数据清洗要求 四、实现代码 1.数据采集 2.数据清洗 资源链接 下面有笔者所放的源码下载链接&#xff0c;读者可自行下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1YmTdlnbSJLvLrrx92zz6Qg 提取码&…...

Microsoft Visual C++ Redistributable 【安装包】【高速下载】

方法1、可以从官方下载&#xff0c;如下图 Visual C Redistributable for Visual Studio 2015 但是此链接只有一个版本 方法2 已经下载好并且已经整理好了2008--2022的所有版本点击下方链接即可高速下载 如果是win7-win8-win10-win11直接可以下载2015--2022版本&#xff0c…...

MFC绘制哆啦A梦

文章目录 OnPaint绘制代码完整Visual Studio工程下载其他卡通人物绘制 OnPaint绘制代码 CPaintDC dc(this); // 用于绘画的设备上下文CRect rc;GetWindowRect(rc);int cxClient rc.Width();int cyClient rc.Height();// 辅助线HPEN hPen CreatePen(PS_DOT, 1, RGB(192, 192,…...

网络编程(TCP协议,UDP协议)

目录 网络编程三要素 IP IPv4 InetAddress类 端口号 协议 UDP协议 UDP协议发送数据 UDP协议接收数据 UDP的三种通信方式(代码实现) TCP协议 TCP通信程序 三次握手和四次挥手 练习 1、客户端:多次发送数据服务器:接收多次接收数据&#xff0c;并打印 2、客户端…...

读取Jar包下文件资源的问题及解决方案

问题 项目A代码调用到Resouces下的文件a.sh&#xff0c;打包成Jar包后&#xff0c;项目B调用对应方法时&#xff0c;出现报错&#xff0c;找不到a.sh文件路径&#xff0c;原来的代码可能是&#xff1a; URL resource getClass().getClassLoader().getResource("a.sh&qu…...

C++ 反转一个二进制串

描述 一个32位有符号整数&#xff0c;用二进制编码来表示。现需要将该二进制编码按位反转&#xff0c;计算出反转后的值。 示例1 输入&#xff1a; 1 返回值&#xff1a; -2147483648 说明&#xff1a; 00000000 00000000 00000000 00000001 翻转后为 10000000 000000…...

黑神话悟空-吉吉国王版本【抢先版】

在中国的游戏市场中&#xff0c;一款名为“黑神话悟空”的游戏引起了广泛的关注。这款游戏以中国传统的神话故事“西游记”为背景&#xff0c;创造了一个令人震撼的虚拟世界。今天&#xff0c;我们要来介绍的是这款游戏的一种特殊版本&#xff0c;那就是吉吉国王版本。 在吉吉国…...

【尚庭公寓SpringBoot + Vue 项目实战】预约看房与租约管理(完结)

【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09;1、业务说明2、接口开发2.1、预约看房管理2.1.1.保存或更新看房预约2.1.2. 查询个人预约…...

java拼图小游戏项目

创建一个Java拼图小游戏是一个有趣且富有教育意义的项目&#xff0c;可以锻炼你的编程技能。以下是开发一个基本拼图游戏可能需要考虑的几个步骤&#xff1a; 项目规划&#xff1a; 确定游戏的基本规则和玩法。设计游戏的界面和用户交互。 环境搭建&#xff1a; 确保你的开发环…...

[C++][数据结构][跳表]详细讲解

目录 0.什么是跳表&#xff1f;1.SkipList的优化思路2.SkipList的效率如何保证&#xff1f;3.SkipList实现4.SkipList VS 平衡搜索树 && Hash 0.什么是跳表&#xff1f; SkipList本质上也是一种查找结构&#xff0c;用于解决算法中的查找问题&#xff0c;跟平衡搜索树…...

tinyxml

github下载相关的软件包&#xff0c;其中有四个文件需要主要需要关注就是分别是tinyxml12.cpp&#xff0c;tinyxml12.h&#xff0c;rss网页xml文件&#xff0c;还有就是官方给的test文件tinyxmltest.cpp。 example1就是提供一个打开文件的方式 int example_1() {XMLDocument …...

Docker(三)-Docker常用命令

1.run run命令执行流程:2.帮助启动类命令 2.1 启动docker systemctl start docker2.2 停止docker systemctl stop docker2.3 重启docker systemctl restart docker2.4查看docker状态 systemctl status docker2.5开机启动 systemctl enable docker2.6查看docker概要信息 …...

[MRCTF2020]PixelShooter

一个apk文件 jeb打开发现是apk文件 apk游戏逆向必须知道的知识: 一般关键数据在 Assets/bin/data/managed/assembly-csharp.dll这个文件里面 我不知道jeb为什么这里我没有 apk是个压缩包 直接解压 这个文件解压也可以发现flag {Unity_1S_Fun_233}...

vue实现的商品列表网页

一、商品列表效果如下 二、代码&#xff1b; vue实现的商品列表网页 &#xff0c; 图片在vue项目的Public文件夹里的 imgs中 <template><div class"common-layout"><!-- el-container:外层容器。 当子元素中包含 <el-header> 或 <el-foo…...

【泛微系统】e-cology非标配功能概览

关于泛微非标功能的功能编号、功能名称及支持版本 编号名称支持版本001考勤功能4.500.0124-9.00+KB900190206002短信通用接口5.000.0327+KB50001003 及以上版本004计划任务接口5.0+KB50001003及以上版本005集成登录接口6.0及以上版本006流程中自定义浏览框5.0+KB50001003及以上…...

Python基础教程(二十八):pip模块

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…...

通信系统概述

1.定义 通信系统&#xff08;也称为通信网络&#xff09;是利用各种通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来&#xff0c;依靠网络软件及通信协议实现资源共享和信息传递的系统。 2.概述 随着通信技术和网络技术的不断发展&#xff…...

http发展史(http0.9、http1.0、http1.1、http/2、http/3)详解

文章目录 HTTP/0.9HTTP/1.0HTTP/1.1队头阻塞&#xff08;Head-of-Line Blocking&#xff09;1. TCP 层的队头阻塞2. HTTP/1.1 的队头阻塞 HTTP/2HTTP/3 HTTP/0.9 发布时间&#xff1a;1991年 特点&#xff1a; 只支持 GET 方法没有 HTTP 头部响应中只有 HTML 内容&#xff0…...

Hadoop 面试题(四)

1. 简述Hadoop节点的动态上线下线的大概操作 &#xff1f; 在Hadoop集群中&#xff0c;节点的动态上下线指的是在不停止整个集群服务的情况下&#xff0c;添加或移除节点。这种能力对于维护和扩展集群非常重要。以下是Hadoop节点动态上线下线的大概操作步骤&#xff1a; 动态…...

绽放光彩的小程序 UI 风格

绽放光彩的小程序 UI 风格...

电脑文件夹怎么加密?文件夹加密的5种方法

在数字化时代&#xff0c;信息安全显得尤为重要。对于个人电脑用户来说&#xff0c;文件夹加密是一种有效保护隐私和数据安全的方法。本文将介绍五种文件夹加密的方法&#xff0c;帮助您更好地保护自己的重要文件。 如何设置文件夹密码方法一&#xff1a;利用Windows系统自带的…...

异步复位同步释放

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 题目描述&#xff1a; 请使用异步复位同步释放来将输入数据a存储到寄存器中&#xff0c;并画图说明异步复位同步释放的机制原理 信号示意图&#xff1a; clk为时钟 rst_n为低电平复位 d信号输入…...

做国外网站用什么颜色/潍坊网站seo

网上各种的说法&#xff0c;不外乎这么几种 第一种简单的说呢就是这样的&#xff1a; 第一步&#xff1a;客户机提出域名解析请求,并将该请求发送给本地的域名服务器。 第二步&#xff1a;当本地的域名服务器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名服务器…...

莘县建设局网站/网站ip查询

基于CentOS 6.5操作系统搭建MongoDB服务Mongo DB ,是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式,备受当前IT从业人员的青睐。Mongo DB很好的实现了面向对象的思想(OO思想),在Mongo DB中每一条记录都是一个Document对象。Mongo DB最大的优势在于所有…...

微商网站/软文推广系统

30行代码实现纯CSS—3种换肤 老规矩&#xff0c;先把代码给大家&#xff0c;拿去粘贴直接用&#xff0c;无需引用&#xff0c;不好用评论底下随便喷&#xff0c;我一条一条看。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UT…...

织梦云建站系统/宁波品牌网站推广优化公司

[20160831]关于数据块Checksum.txt --以前我学习bbed时做过一些测试,将AAAA替换成BBBB,你可以发现数据块的Checksum并没有发生变化,当时并没有仔细探究, --现在想起来计算Checksum算法应该相对简单,就是做异或操作. --比如上面的字符AAAA如果2个字符按位做异或操作,变成0000000…...

开发区建设集团网站/使用百度地图导航收费吗

1、 一个".java"源文件中是否可以包括多个类&#xff08;不是内部类&#xff09;&#xff1f;有什么限制&#xff1f;、 可以有多个类&#xff0c;但只能有一个public的类&#xff0c;并且public的类名与文件名相同 2、 Java有没有goto? Java中的保留字&#xff0…...

徐州制作公司网站/seo综合查询平台官网

灰度图是指用灰度表示的图像&#xff0c;灰度是在白色和黑色之间分的若干个等级&#xff0c;其中最常用的是256级&#xff0c;也就是256级灰度图。灰度图在医学、航天等领域有着广泛的应用。 那么如何将一幅彩色图像转换为灰度图呢&#xff1f;根据人眼对红绿蓝三色的敏感程度&…...