JAVA TCP协议初体验
文章目录
- 一、需求概述
- 二、设计选择
- 三、代码结构
- 四、代码放送
- 五、本地调试
- 1. 服务端日志
- 2. 客户端日志
- 3. 断线重连日志
- 六、服务器部署运行
- 1. 源码下载
- 2. 打包镜像
- 3. 运行容器
一、需求概述
最近开发某数据采集系统,系统整体的数据流程图如下:
同时,数据中心又需要下发命令到某客户端执行,客户端执行完成后将结果通知到数据中心。
二、设计选择
考虑功能点:
- 客户端多个,一段时间内数量可控相对固定。
- 客户端主动连接服务端,支持断线重连。
- 客户端与服务端支持双向通信。
选择TCP协议作为客户端与数据中心之间的交互协议比较合适,数据中心服务器作为tcp-server开放端口供tcp-client连接。
三、代码结构
四、代码放送
https://gitcode.com/00fly/tcp-show
或者使用下面的备份文件恢复成原始的项目代码
如何恢复,请移步查阅:神奇代码恢复工具
//goto docker\docker-compose.yml
version: '3.7'
services:tcp-server:image: registry.cn-shanghai.aliyuncs.com/00fly/tcp-show-server:0.0.1container_name: tcp-serverdeploy:resources:limits:cpus: '1.0'memory: 64Mreservations:cpus: '0.05'memory: 64Mports:- 8000:8000restart: on-failurelogging:driver: json-fileoptions:max-size: '5m'max-file: '1'tcp-client:image: registry.cn-shanghai.aliyuncs.com/00fly/tcp-show-client:0.0.1container_name: tcp-clientdepends_on:- tcp-serverdeploy:resources:limits:cpus: '1.0'memory: 64Mreservations:cpus: '0.05'memory: 64Mrestart: on-failureenvironment:#- TCP_SERVER=192.168.15.202- TCP_SERVER=tcp-serverlogging:driver: json-fileoptions:max-size: '5m'max-file: '1'
//goto docker\restart-server.sh
#!/bin/bash
docker-compose down tcp-server
sleep 10
docker-compose up -d tcp-server
docker logs -f tcp-server
//goto docker\restart.sh
#!/bin/bash
docker-compose down && docker-compose up -d
sleep 2
docker logs -f network-server
//goto docker\stop.sh
#!/bin/bash
docker-compose down
//goto Dockerfile
#基础镜像
#FROM openjdk:8-jre-alpine
FROM adoptopenjdk/openjdk8-openj9:alpine-slimRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \echo 'Asia/Shanghai' >/etc/timezone#拷贝发布包
COPY target/*.jar /app.jar#启动脚本
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Xshareclasses", "-Xquickstart", "-jar", "/app.jar"]
//goto pom-client.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fly</groupId><artifactId>tcp-show</artifactId><version>0.0.1</version><name>tcp-show</name><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub><java.version>1.8</java.version><skipTests>true</skipTests></properties><dependencies><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.12.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.10</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency></dependencies><build><finalName>${project.artifactId}-client-${project.version}</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><!-- 方式一:带dependencies运行包 --><plugin><artifactId>maven-assembly-plugin</artifactId><version>3.5.0</version><configuration><!-- 是否添加assemblyId --><appendAssemblyId>false</appendAssemblyId><archive><manifest><mainClass>com.fly.protocol.tcp.run.StartClient</mainClass></manifest></archive><descriptorRefs><!--将所有外部依赖JAR都加入生成的JAR包 --><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><!-- 配置执行器 --><id>make-assembly</id><phase>package</phase><!-- 绑定到package阶段 --><goals><goal>single</goal><!-- 只运行一次 --></goals></execution></executions></plugin><!-- 添加docker-maven插件 --><plugin><groupId>io.fabric8</groupId><artifactId>docker-maven-plugin</artifactId><version>0.40.3</version><executions><execution><phase>package</phase><goals><goal>build</goal><!--<goal>push</goal>--><!--<goal>remove</goal>--></goals></execution></executions><configuration><!-- 连接到带docker环境的linux服务器编译image --><!-- <dockerHost>http://192.168.182.10:2375</dockerHost> --><!-- Docker 推送镜像仓库地址 --><pushRegistry>${docker.hub}</pushRegistry><images><image><name>${docker.hub}/00fly/${project.artifactId}-client:${project.version}</name><build><dockerFileDir>${project.basedir}</dockerFileDir></build></image></images></configuration></plugin></plugins></build>
</project>
//goto pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fly</groupId><artifactId>tcp-show</artifactId><version>0.0.1</version><name>tcp-show</name><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub><java.version>1.8</java.version><skipTests>true</skipTests></properties><dependencies><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.12.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.10</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency></dependencies><build><finalName>${project.artifactId}-server-${project.version}</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><!-- 方式一:带dependencies运行包 --><plugin><artifactId>maven-assembly-plugin</artifactId><version>3.5.0</version><configuration><!-- 是否添加assemblyId --><appendAssemblyId>false</appendAssemblyId><archive><manifest><mainClass>com.fly.protocol.tcp.run.StartServer</mainClass></manifest></archive><descriptorRefs><!--将所有外部依赖JAR都加入生成的JAR包 --><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><!-- 配置执行器 --><id>make-assembly</id><phase>package</phase><!-- 绑定到package阶段 --><goals><goal>single</goal><!-- 只运行一次 --></goals></execution></executions></plugin><!-- 添加docker-maven插件 --><plugin><groupId>io.fabric8</groupId><artifactId>docker-maven-plugin</artifactId><version>0.40.3</version><executions><execution><phase>package</phase><goals><goal>build</goal><!--<goal>push</goal>--><!--<goal>remove</goal>--></goals></execution></executions><configuration><!-- 连接到带docker环境的linux服务器编译image --><!-- <dockerHost>http://192.168.182.10:2375</dockerHost> --><!-- Docker 推送镜像仓库地址 --><pushRegistry>${docker.hub}</pushRegistry><images><image><name>${docker.hub}/00fly/${project.artifactId}-server:${project.version}</name><build><dockerFileDir>${project.basedir}</dockerFileDir></build></image></images></configuration></plugin></plugins></build>
</project>
//goto src\main\java\com\fly\protocol\tcp\bio\TcpClient.java
package com.fly.protocol.tcp.bio;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;import lombok.extern.slf4j.Slf4j;@Slf4j
public class TcpClient implements Runnable
{private String ip;private int port;private Socket socket;private DataOutputStream dataOutputStream;private String clientName;private boolean isClientCoreRun = false;private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);private ExecutorService executor = Executors.newFixedThreadPool(2);public TcpClient(String clientName){super();this.clientName = clientName;}/*** * @param ip 服务端IP* @param port 服务端PORT* @return*/public boolean connectServer(String ip, int port){try{this.ip = ip;this.port = port;socket = new Socket(InetAddress.getByName(ip), port);log.info("****** TcpClient will connect to Server {}:{}", ip, port);scheduler.scheduleAtFixedRate(this::checkConnection, 0, 10, TimeUnit.SECONDS);isClientCoreRun = true;dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF(clientName);dataOutputStream.flush();}catch (IOException e){log.error(e.getMessage());isClientCoreRun = false;}return isClientCoreRun;}/*** 检查TCP连接*/private void checkConnection(){if (socket == null || socket.isClosed()){log.error("Connection lost, attempting to reconnect");reconnect();}}private void reconnect(){try{socket = new Socket(InetAddress.getByName(ip), port);log.info("****** TcpClient will connect to Server {}:{}", ip, port);isClientCoreRun = true;executor.execute(new ReceiveMsg());dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF(clientName);dataOutputStream.flush();}catch (IOException e){log.error(e.getMessage());isClientCoreRun = false;}}/*** 发送报文*/public void sendMsg(String msg){try{dataOutputStream.writeUTF(msg);dataOutputStream.flush();}catch (IOException e){log.error(e.getMessage());closeClientConnect();}}/*** 断开客户端与服务端的连接*/public void closeClientConnect(){if (dataOutputStream != null){try{dataOutputStream.close();isClientCoreRun = false;if (socket != null){socket.close();}}catch (IOException e){log.error(e.getMessage());}}}@Overridepublic void run(){executor.execute(new ReceiveMsg());// 发送数据scheduler.scheduleAtFixedRate(() -> {sendMsg(RandomStringUtils.randomAlphanumeric(10));}, RandomUtils.nextInt(1, 10), 10, TimeUnit.SECONDS);}class ReceiveMsg implements Runnable{private DataInputStream dataInputStream;public ReceiveMsg(){try{// 数据输入流dataInputStream = new DataInputStream(socket.getInputStream());}catch (IOException e){log.error(e.getMessage());}}@Overridepublic void run(){try{// server停止后, 会影响接受消息线程工作while (isClientCoreRun){String msg = dataInputStream.readUTF();log.info("{} get msg: {}", clientName, msg);}}catch (IOException e){log.error(e.getMessage());// 防止重连失败closeClientConnect();}}}
}
//goto src\main\java\com\fly\protocol\tcp\bio\TcpServer.java
package com.fly.protocol.tcp.bio;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;import lombok.extern.slf4j.Slf4j;@Slf4j
public class TcpServer implements Runnable
{private ServerSocket serverSocket;private boolean isServerCoreRun = false;private Map<String, NewClient> allClient = new HashMap<>();public boolean startServer(String ip, int port){try{serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(ip, port));isServerCoreRun = true;}catch (IOException e){log.error(e.getMessage());isServerCoreRun = false;}return isServerCoreRun;}/*** 关闭服务** #1 断开与所有客户端的连接,并将客户端容器中的所有已连接的客户端清空。 #2 关闭服务器套接字*/public void closeServer(){try{isServerCoreRun = false;for (Map.Entry<String, NewClient> all : this.allClient.entrySet()){all.getValue().isNewClientRun = false;all.getValue().socket.close();}allClient.clear();serverSocket.close();}catch (IOException e){log.error(e.getMessage());}}/*** 向客户端发送报文*/public void sendMsg(String clientName, String msg){if (allClient.containsKey(clientName)){allClient.get(clientName).sendMsg(msg);}}@Overridepublic void run(){try{log.info("TcpServer will start");while (isServerCoreRun){// 阻塞式等待客户端连接Socket socket = serverSocket.accept();String clientName = new DataInputStream(socket.getInputStream()).readUTF();String clientIP = socket.getInetAddress().getHostAddress();int clientPort = socket.getPort();String clientConnectDateTime = DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss");NewClient newClient = new NewClient(socket, clientName, clientIP, clientPort, clientConnectDateTime);allClient.put(clientName, newClient);log.info("**** add new client ===> {}", allClient.keySet());new Thread(newClient).start();}}catch (IOException e){log.error(e.getMessage());}}class NewClient implements Runnable{// 客户端套接字private Socket socket;// 数据输入流private DataInputStream dataInputStream;// 数据输出流private DataOutputStream dataOutputStream;// 客户端运行(收、发报文)状态private boolean isNewClientRun = true;// 客户端的名称private String clientName;// 客户端的IP地址private String clientIP;public NewClient(){}// 构造方法初始化成员属性public NewClient(Socket socket, String clientName, String clientIP, int clientPort, String clientConnectDateTime){this.socket = socket;this.clientName = clientName;this.clientIP = clientIP;try{// 创建客户端数据输入、输出流dataInputStream = new DataInputStream(socket.getInputStream());dataOutputStream = new DataOutputStream(socket.getOutputStream());}catch (IOException e){log.error(e.getMessage());closeCurrentClient();}}@Overridepublic void run(){try{// 客户端在运行才能收发报文while (this.isNewClientRun){// 获取到客户端发送的报文String msg = dataInputStream.readUTF();if (StringUtils.isNotBlank(msg)){log.info("clientName: {}, clientIP: {}, send msg ===> {}", clientName, clientIP, msg);}// 向客户端传送数据int index = 0;for (String key : allClient.keySet()){index++;if (StringUtils.equals(key, clientName)){allClient.get(key).sendMsg("from server: " + msg + StringUtils.repeat("-----", index));}}}}catch (IOException e){log.error(e.getMessage());closeCurrentClient();}}/*** 断开当前客户端的连接释放资源*/public void closeCurrentClient(){try{// 结束客户端的运行状态isNewClientRun = false;// 断开数据输出出流if (dataOutputStream != null){dataOutputStream.close();}// 断开数据输入出流if (dataInputStream != null){dataInputStream.close();}// 断开客户端套解析if (socket != null){socket.close();}// 将该客户端从客户端容器中删除allClient.remove(clientName);log.info("**** remove client ===> {}", allClient.keySet());}catch (IOException e){log.error(e.getMessage());}}/*** 发送报文*/public void sendMsg(String msg){try{// 发送报文dataOutputStream.writeUTF(msg);// 清空报文缓存dataOutputStream.flush();}catch (IOException e){log.error(e.getMessage());closeCurrentClient();}}}
}
//goto src\main\java\com\fly\protocol\tcp\run\StartClient.java
package com.fly.protocol.tcp.run;import java.util.stream.IntStream;import org.apache.commons.lang3.StringUtils;import com.fly.protocol.tcp.bio.TcpClient;public class StartClient
{public static void main(String[] args){// docker环境下优先使用docker-compose中environment值String serverIp = StringUtils.defaultIfBlank(System.getenv().get("TCP_SERVER"), "127.0.0.1");IntStream.rangeClosed(1, 3).forEach(i -> {TcpClient client = new TcpClient("CLIENT_" + i);if (client.connectServer(serverIp, 8000)){new Thread(client).start();}});}
}
//goto src\main\java\com\fly\protocol\tcp\run\StartServer.java
package com.fly.protocol.tcp.run;import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;import com.fly.protocol.tcp.bio.TcpServer;public class StartServer
{public static void main(String[] args){TcpServer server = new TcpServer();if (server.startServer("0.0.0.0", 8000)){Executors.newScheduledThreadPool(2).scheduleAtFixedRate(() -> {int index = RandomUtils.nextInt(1, 4);server.sendMsg("CLIENT_" + index, "random: " + RandomStringUtils.randomAlphanumeric(10));}, 10, 60, TimeUnit.SECONDS);new Thread(server).start();}}
}
//goto src\main\resources\log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="off" monitorInterval="0"><appenders><console name="Console" target="system_out"><patternLayoutpattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n" /></console></appenders><loggers><root level="INFO"><appender-ref ref="Console" /></root></loggers>
</configuration>
五、本地调试
先后启动StartServer、StartClient
1. 服务端日志
2. 客户端日志
3. 断线重连日志
六、服务器部署运行
1. 源码下载
在安装好jdk、maven、docker环境的服务器下载源码
git clone https://gitcode.com/00fly/tcp-show.git
2. 打包镜像
#server打包
mvn clean package#client打包
mvn clean package -f pom-client.xml
3. 运行容器
上传docker文件目录到服务器,执行
sh restart.shsh restart-server.shdocker logs -f tcp-server
docker logs -f tcp-client
有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!
-over-
相关文章:

JAVA TCP协议初体验
文章目录 一、需求概述二、设计选择三、代码结构四、代码放送五、本地调试1. 服务端日志2. 客户端日志3. 断线重连日志 六、服务器部署运行1. 源码下载2. 打包镜像3. 运行容器 一、需求概述 最近开发某数据采集系统,系统整体的数据流程图如下: #mermaid…...

sqlserver迁移数据库文件存储位置
业务背景:由于C盘爆满,需要将数据库文件迁移到别处比如D盘 下面以某一个数据库转移为示例:(可以用SSMS工具,新建查询配合使用) 1.查询数据库文件存储路径 sql语句: -- 查询路径 USE QiangTes…...
配置项取值给静态类用
在 Java 中,如果要从 application.yml 文件中取值并供静态类使用,可以考虑以下几种方法: 一、使用 Spring 的 Environment 类 1. 首先确保你的项目是一个 Spring 项目,并且配置文件被正确加载。 2. 在需要获取配置值的类中注入…...

【vs code(cursor) ssh连不上服务器】但是 Terminal 可以连上,问题解决 ✅
问题描述 通过 vs code 的 ssh 原本方式无法连接,但是通过 Terminal 使用相同的 bash 却可以连接上服务器。 ssh -p 4xx username14.xxx.3 问题解决方法 在 vs code 的 config 里,将该服务器(14.xxx.3)的相关配置全部清空或注释…...

Go基础学习06-Golang标准库container/list(双向链表)深入讲解;延迟初始化技术;Element;List;Ring
基础介绍 单向链表中的每个节点包含数据和指向下一个节点的指针。其特点是每个节点只知道下一个节点的位置,使得数据只能单向遍历。 示意图如下: 双向链表中的每个节点都包含指向前一个节点和后一个节点的指针。这使得在双向链表中可以从前向后或从后…...

多层时间轮原理以及使用
文章目录 背景常用定时器实现 任务队列时间轮介绍基本结构指针移动定时任务插入循环任务插入代码示例 多层时间轮使用流程 代码 背景 在软件开发中,定时器是一个极为常用的组件,它发挥着至关重要的作用。通过定时器,开发者能够精确地控制程序…...

鸿蒙HarmonyOS开发生态
1、官网 华为开发者联盟-HarmonyOS开发者官网,共建鸿蒙生态 2、开发工具IDE下载及使用 https://developer.huawei.com/consumer/cn/ 3、使用帮助文档 4、发布到华为应用商店 文档中心...
vue中使用jsencrypt加密
vue中封装并使用jsencrypt加密 一般在项目搭建过程中用户注册、登录、修改密码、重置密码等功能都需要用到密码加密的功能,所以把jsencrypt进行封装使用,使代码更加简洁,流程如下: 1、安装jsencrypt npm install jsencrypt2、在…...
SpirngBoot核心思想之一AOP
简介: AOP(Aspect-Oriented Programming,面向切面编程) 是一种用于解决软件系统中横切关注点的编程范式。在企业级开发中,很多非业务功能(如日志、事务、权限、安全等)需要在多个模块中执行&am…...

足球预测推荐软件:百万数据阐述百年足球历史-大数据模型量化球员成就值
我开始创建这个模型是从梅西22世界杯夺冠第二天开始准备的,当时互联网上充斥了太多了个人情感的输出,有的人借题对C罗冷嘲热讽,有的人质疑梅西的阿根廷被安排夺冠不配超越马拉多纳做GOAT。作为一个从2002年开始看球的球迷,说实话有…...

AD中如何批量修改丝印的大小,节省layout时间
先选中一个元器件的丝印,然后右键,选择“查找相似项” 直接点击OK,这时会发现所有的丝印都会被选中 然后点击右上角的按键,修改其属性。...

Ps:堆栈
将多张类似的图像图层堆叠在一起形成图像堆栈 Stack,通过应用不同的堆栈模式,可以从这些图像中提取有用的信息或达到特定的视觉效果。 Photoshop 中的堆栈技术被广泛应用于摄影后期处理、科学研究、环境监测与分析等领域。 例如,它常用于减少…...
獨立IP和共用IP有什麼區別?
什麼是獨立IP? 獨立IP指的是一個IP地址專屬於一個用戶或設備。無論是網站、伺服器還是其他線上服務,獨立IP都意味著該IP地址不會與其他用戶或設備共用。獨立IP通常用於需要高安全性和穩定性的場景,比如企業網站、電子商務平臺和需要SSL證書的…...

枢纽云EKP数字门户模板上线!轻松复刻胖东来官网,实现数字化逆袭
数字化转型的浪潮中,胖东来凭借着其独特的企业文化和对员工福利的重视,走进了大众视野。近期,胖东来推出了“不开心假”等员工关怀,又一次引发了大众的广泛关注。这种关怀不仅仅提升了员工的幸福感,也间接的改善了顾客…...

从自动化到智能化:AI如何推动业务流程自动化
引言:从自动化到智能化的必然趋势 在当今数字化时代,企业为了提升效率、降低成本,纷纷采用自动化技术来简化重复性任务。然而,传统自动化仅限于标准化操作,无法应对复杂的决策和多变的市场环境。随着人工智能ÿ…...

Selenium与数据库结合:数据爬取与存储的技术实践
目录 一、Selenium与数据库结合的基础概念 1.1 Selenium简介 1.2 数据库简介 1.3 Selenium与数据库结合的优势 二、Selenium爬取数据的基本步骤 2.1 环境准备 2.2 编写爬虫代码 2.3 数据提取 2.4 异常处理 三、数据存储到数据库 3.1 数据库连接 3.2 数据存储 3.3 …...

在 Docker 中进入 Redis 容器后,可以通过以下方法查看 Redis 版本:
文章目录 1、info server2、redis-cli -v 1、info server [rootlocalhost ~]# docker exec -it spzx-redis redis-cli 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> info server # Server redis_version:6.2.6 redis_git_sha1:00000000 redis_git_dirty:0 redis_bui…...

Windows 10 系统安装 FFmpeg 查看、转换、编辑音频文件
1、FFmpeg官网:FFmpeg 点击下载 可以选择下载full版本 下载之后解压到指定目录,在系统环境变量 Path 里面新增环境变量 打开CMD终端运行 ffmpeg -version 查看是否安装成功。 2、基本命令 查看音频基本信息 ffprobe 1.mp3 ##输出 [mp3 000002ab334405…...

反调试防护-API
IsDebuggerPresent() CheckRemoteDebuggerPresent() 其内部实际调用NtQueryInformationProcess() bool _stdcall ThreadCall() {while (true){BOOL pbDebuggerPresent FALSE;CheckRemoteDebuggerPresent(GetCurrentProcess(), &pbDebuggerPresent);if (pbDebuggerPres…...

【视频讲解】非参数重采样bootstrap逻辑回归Logistic应用及模型差异Python实现
全文链接:https://tecdat.cn/?p37759 分析师:Anting Li 本文将深入探讨逻辑回归在心脏病预测中的应用与优化。通过对加州大学欧文分校提供的心脏病数据集进行分析,我们将揭示逻辑回归模型的原理、实现过程以及其在实际应用中的优势和不足…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...