引言
有图有真相,那短视频就更是真相了。下面是三大语言的短视频。
Java源码版云控示例:
Net源码版云控示例:
Net源码版云控示例在线视频亚丁号-知识付费平台 支付后可见 扫码付费可见
Python源码版云控示例:
Pythont源码版云控示例在线视频亚丁号-知识付费平台 支付后可见 扫码付费可见
核心技术:各个编程语言的WebSocket技术。
Java:Nettey、Net:Fleck、Python:Tornado、Autojs:自带的WS.都 写了很多代码感觉还是Java 的Nettey强大,用到的技术做个罗列。
Java:
- java版本 JDK8(64bit)
- 开发IDE IntelliJ IDEA 2020.1.1
- Web框架 SpringB oot2.6.4
- 模板框架 Thymeleaf 2.2.2 (Spring推荐款个人感觉不好用)
- UI框架BootStrap3
- 数据库框架Hibernate5.3.1
- WebSocket 框架 Nettey 4.1.65
- Json框架 Gson2.8.8
- Zip压缩框架 zip4j2.9.1
- 数据库Mysql56
- 错误日志 spring自带的
- 其他 java的反射记录日志、 spring 的拦截器判断session、简化实体类插件lombok
Python
- Python版本 python3.7(64bit)
- 开发IDE Pycharm
- Web框架 Flask 2.2.5
- 模板框架Flask自带的Jinja2 3.1.2
- UI框架BootStrap3
- 数据库框架SQLAlchemy 2.0.16
- WebSocket 框架 Tornado 6.2
- Json框架 ujson5.7.0
- Zip压缩框架ZIPP 3.15.0
- 数据库Mysql56
NET(C#)
- Net版本 Net Core3.1 后继会升级至NET7
- IDE visual studio 2022
- Web框架 Net Core3.1 MVC
- UI框架BootStrap3
- 数据库框架Dapper 2.0.78
- WebSocket 框架 Fleck 1.1
- Json框架
- Zip压缩框架 dotnetzip 1.16.0
- 数据库Mysql56
技术篇
从技术的成熟度、稳定性、适应性到应用广度这里以Java为例子进行讲解。
核心技术(通信技术)
核心技术就是WebSocket。2011年WebSocket API被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
最主要还解决Ajax轮询带来的延迟和服务器性能损耗。
本软件服务端建立WS服务器,客户端进行连接,连接成功后进行双工通信,服务端发送任务,客户端发送【ping】。客户端是Autojs7.服务端采用了Java、net和Python多种语言的支持。网页JS连接服务端网上一大堆故此很容易,然autojs的对面的技术控看过来。这里的技术很精彩。
本软件重点解决2大问题:
一、热更
单JS脚本不可能解决所以问题,找图工作就不行因此客户端执行project势在必行,然项目的更新必然是个大问题。本项目完美解决服务端发送项目的事宜,无论是自动阅读的js还是自动阅读的project都进行完美热更。
二、断线重连
服务器宕机、WS服务重启或客户端重启都需要再次链接WS服务,然再次链接的WebSocket对象与之前的对象不一致导致客户端无法发送任务和命令。
此项目已经解决再次链接的问题且WS为同一个对象
服务端(Java)
项目结构
严格按照Java项目的命名规则进行包的命名,其中的一些方法为了迎合Net的写法故此首字母大写了。
从上到下依次介绍:
- controller文件夹是控制器见名知意
- dao是数据访问层
- demo是一些示例的demo发布的时候可以删除
- entity是实体类,这个仿照Net的叫法,里面有po和vo文件夹.
- framework这个是核心框架,在框架章节会详细介绍。
- plugin项目使用的插件和工具
- service项目的dao与controller交互的层,理论上controller层是不准写业务代码和sql语句的
- timer定时器目前只是检查ws的客户端是否断线
- static 存放的是js脚本和css类和图片等信息
- templates存放的是html页面
上面的图我使用的是【packages】模式,static和templates必须这么起名,springboot就这么查询和要求的,这个和Python的Flask比较类似。
Maven文件
项目采用的是Maven使用的是IDEA。下图是引入的jar包。
<!-- 获取计算机信息 -->
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>1.6.4</version>
</dependency>
<!-- netty 主要是ws功能 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.65.Final</version>
</dependency>
<!-- zip -->
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.9.1</version>
</dependency>
后端Java框架
整个项目的核心,项目的基础文件,基础框架功能不是很多大家多多海涵,
功能如下:
- 数据加密,目前采用的是Base64.UI端使用统一的Ajax方法Post数据Java端使用统一的方法接收参数(会解密参数)。示例:
- 自动构建实体类
- 自动写操作日志
通过反射方法进行日志的记录。
@Logger(description = "访问用户管理页面")
- BaseController提供各种写Json的方法同时也提供是否加密的算法
- BaseDataAccess提供HIB5的数据库访问session
- 提供数据库返回多参数方法统一对象ResultEntity
- 提供各种操作的工具类
前端UI框架
前端技术主要是BootStrap3和Jquery2,其中BS3封装的H+Plugins框架(公司不知道在哪里搞到的)JQ2 我自己封装了一下形成yadinghao.js文件,配合BS3的H+使用。
UI
H+4.9 下载地址:
百度网盘 请输入提取码 提取码:6666
JS
自定义的JS框架yadinghao.js使用JQ进行了2次封装。主要是针对Ajax的get和post进行了封装。
1、主要使用AjaxPost方法:请求地址、请求参数、回调函数、是否同步和是否加密。调用示例:
2、另一个主要封装插件:
这个插件基本每个页面都使用 。默认是加密的,没有做出参数。
3、另外封装的就是toast 这个最常用
4、还有一些其他小方法大家自行观看 吧。
数据库(Hib)
数据使用的是Mysql,版本是5.6.DBMS使用的是Navicat15.数据库设计工具是powerdegisn15.
数据访问使用的是Hibernate5(数据量不是很大,且开发效率高于MyBatis).配置文件需要在resources 下,Spring就自动寻了。
WebSocket
代码位置
ws是本软件的核心故此将其代码单独存放,路径是:com.yadinghao.service.websocket包下面的都是和ws相关的代码。真像如下:
核心思想
- 构建在线列表,存放服务端页面和客户端手机
- 认证通过的设备才可以加入到在线列表(需要客户端提起注册)
- 认证通过的设备会通知到服务端注册认证页面。页面可以进行发布命令和任务操作。
- 客户端接收任务或命令进行执行操作
- 客户端掉线后服务端会依据IP和端口号对设备进离线操作
- 客户端掉线后未触发服务端离线操作会丢失ping服务器的数据,服务端会依据ping的时间对客户端进行离线操作
- 重点服务端可自定义上传脚本和AJ7的项目,AJ7的格式是zip的(autojs只能解压zip)。上传的js和project版本高于客户端的版本则直接更新
核心页面
- WS开启页面
- 云控设备页面
- 云控任务页面
核心代码
服务端启动WS代码
启动代码
package com.yadinghao.service.websocket;
import com.yadinghao.framework.entity.ResultEntity;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import java.net.InetSocketAddress;
public class WebSocketBusiness {
EventLoopGroup bossGroup = null;
EventLoopGroup workerGroup = null;
Channel channel = null;
public ResultEntity startWebSocket(String wsAddress, String userId) throws InterruptedException {
ResultEntity resultEntity=new ResultEntity();
String[] split = wsAddress.replace("ws:\\", "").replace("\\", "").replace("ws://", "").split(":");
String ipAddress= split[0];
String strPort= split[1].trim();
int port=Integer.parseInt(strPort);
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(ipAddress, port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec()); // HTTP 协议解析,用于握手阶段
pipeline.addLast(new HttpObjectAggregator(65536)); // HTTP 协议解析,用于握手阶段
pipeline.addLast(new WebSocketServerCompressionHandler()); // WebSocket 数据压缩扩展
pipeline.addLast(new WebSocketServerProtocolHandler("/", null, true)); // WebSocket 握手、控制帧处理
pipeline.addLast(new WebSocketHandler(wsAddress,userId));
}
});
ChannelFuture f = b.bind().sync();
channel = f.channel();
resultEntity.setReturnValue(true);
return resultEntity;
}
/**
* 关闭NettyWebSocket
* @param primary_key
* @param userId
* @