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

JAVA TCP协议初体验

文章目录

  • 一、需求概述
  • 二、设计选择
  • 三、代码结构
  • 四、代码放送
  • 五、本地调试
    • 1. 服务端日志
    • 2. 客户端日志
    • 3. 断线重连日志
  • 六、服务器部署运行
    • 1. 源码下载
    • 2. 打包镜像
    • 3. 运行容器

一、需求概述

最近开发某数据采集系统,系统整体的数据流程图如下:

数据中心
客户端1
客户端2
客户端3
客户端4

同时,数据中心又需要下发命令到某客户端执行,客户端执行完成后将结果通知到数据中心。

二、设计选择

考虑功能点:

  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. 运行容器 一、需求概述 最近开发某数据采集系统&#xff0c;系统整体的数据流程图如下&#xff1a; #mermaid…...

sqlserver迁移数据库文件存储位置

业务背景&#xff1a;由于C盘爆满&#xff0c;需要将数据库文件迁移到别处比如D盘 下面以某一个数据库转移为示例&#xff1a;&#xff08;可以用SSMS工具&#xff0c;新建查询配合使用&#xff09; 1.查询数据库文件存储路径 sql语句&#xff1a; -- 查询路径 USE QiangTes…...

配置项取值给静态类用

在 Java 中&#xff0c;如果要从 application.yml 文件中取值并供静态类使用&#xff0c;可以考虑以下几种方法&#xff1a; 一、使用 Spring 的 Environment 类 1. 首先确保你的项目是一个 Spring 项目&#xff0c;并且配置文件被正确加载。 2. 在需要获取配置值的类中注入…...

【vs code(cursor) ssh连不上服务器】但是 Terminal 可以连上,问题解决 ✅

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

Go基础学习06-Golang标准库container/list(双向链表)深入讲解;延迟初始化技术;Element;List;Ring

基础介绍 单向链表中的每个节点包含数据和指向下一个节点的指针。其特点是每个节点只知道下一个节点的位置&#xff0c;使得数据只能单向遍历。 示意图如下&#xff1a; 双向链表中的每个节点都包含指向前一个节点和后一个节点的指针。这使得在双向链表中可以从前向后或从后…...

多层时间轮原理以及使用

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

鸿蒙HarmonyOS开发生态

1、官网 华为开发者联盟-HarmonyOS开发者官网&#xff0c;共建鸿蒙生态 2、开发工具IDE下载及使用 https://developer.huawei.com/consumer/cn/ 3、使用帮助文档 4、发布到华为应用商店 文档中心...

vue中使用jsencrypt加密

vue中封装并使用jsencrypt加密 一般在项目搭建过程中用户注册、登录、修改密码、重置密码等功能都需要用到密码加密的功能&#xff0c;所以把jsencrypt进行封装使用&#xff0c;使代码更加简洁&#xff0c;流程如下&#xff1a; 1、安装jsencrypt npm install jsencrypt2、在…...

SpirngBoot核心思想之一AOP

简介&#xff1a; AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09; 是一种用于解决软件系统中横切关注点的编程范式。在企业级开发中&#xff0c;很多非业务功能&#xff08;如日志、事务、权限、安全等&#xff09;需要在多个模块中执行&am…...

足球预测推荐软件:百万数据阐述百年足球历史-大数据模型量化球员成就值

我开始创建这个模型是从梅西22世界杯夺冠第二天开始准备的&#xff0c;当时互联网上充斥了太多了个人情感的输出&#xff0c;有的人借题对C罗冷嘲热讽&#xff0c;有的人质疑梅西的阿根廷被安排夺冠不配超越马拉多纳做GOAT。作为一个从2002年开始看球的球迷&#xff0c;说实话有…...

AD中如何批量修改丝印的大小,节省layout时间

先选中一个元器件的丝印&#xff0c;然后右键&#xff0c;选择“查找相似项” 直接点击OK&#xff0c;这时会发现所有的丝印都会被选中 然后点击右上角的按键&#xff0c;修改其属性。...

Ps:堆栈

将多张类似的图像图层堆叠在一起形成图像堆栈 Stack&#xff0c;通过应用不同的堆栈模式&#xff0c;可以从这些图像中提取有用的信息或达到特定的视觉效果。 Photoshop 中的堆栈技术被广泛应用于摄影后期处理、科学研究、环境监测与分析等领域。 例如&#xff0c;它常用于减少…...

獨立IP和共用IP有什麼區別?

什麼是獨立IP&#xff1f; 獨立IP指的是一個IP地址專屬於一個用戶或設備。無論是網站、伺服器還是其他線上服務&#xff0c;獨立IP都意味著該IP地址不會與其他用戶或設備共用。獨立IP通常用於需要高安全性和穩定性的場景&#xff0c;比如企業網站、電子商務平臺和需要SSL證書的…...

枢纽云EKP数字门户模板上线!轻松复刻胖东来官网,实现数字化逆袭

数字化转型的浪潮中&#xff0c;胖东来凭借着其独特的企业文化和对员工福利的重视&#xff0c;走进了大众视野。近期&#xff0c;胖东来推出了“不开心假”等员工关怀&#xff0c;又一次引发了大众的广泛关注。这种关怀不仅仅提升了员工的幸福感&#xff0c;也间接的改善了顾客…...

从自动化到智能化:AI如何推动业务流程自动化

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

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官网&#xff1a;FFmpeg 点击下载 可以选择下载full版本 下载之后解压到指定目录&#xff0c;在系统环境变量 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实现

全文链接&#xff1a;https://tecdat.cn/?p37759 分析师&#xff1a;Anting Li 本文将深入探讨逻辑回归在心脏病预测中的应用与优化。通过对加州大学欧文分校提供的心脏病数据集进行分析&#xff0c;我们将揭示逻辑回归模型的原理、实现过程以及其在实际应用中的优势和不足…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》

&#x1f9e0; LangChain 中 TextSplitter 的使用详解&#xff1a;从基础到进阶&#xff08;附代码&#xff09; 一、前言 在处理大规模文本数据时&#xff0c;特别是在构建知识库或进行大模型训练与推理时&#xff0c;文本切分&#xff08;Text Splitting&#xff09; 是一个…...

Django RBAC项目后端实战 - 03 DRF权限控制实现

项目背景 在上一篇文章中&#xff0c;我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统&#xff0c;为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...

数据挖掘是什么?数据挖掘技术有哪些?

目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...