JAVA TCP协议初体验

news2024/11/20 12:37:11

文章目录

  • 一、需求概述
  • 二、设计选择
  • 三、代码结构
  • 四、代码放送
  • 五、本地调试
    • 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.1
    container_name: tcp-server
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 64M
        reservations:
          cpus: '0.05'
          memory: 64M
    ports:
    - 8000:8000
    restart: on-failure
    logging:
      driver: json-file
      options:
        max-size: '5m'
        max-file: '1'
        
  tcp-client:
    image: registry.cn-shanghai.aliyuncs.com/00fly/tcp-show-client:0.0.1
    container_name: tcp-client
    depends_on:
      - tcp-server
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 64M
        reservations:
          cpus: '0.05'
          memory: 64M
    restart: on-failure
    environment:
      #- TCP_SERVER=192.168.15.202
      - TCP_SERVER=tcp-server
    logging:
      driver: json-file
      options:
        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-slim

RUN 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());
            }
        }
    }
    
    @Override
    public 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());
            }
        }
        
        @Override
        public 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);
        }
    }
    
    @Override
    public 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();
            }
        }
        
        @Override
        public 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">
			<patternLayout
				pattern="%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.sh

sh restart-server.sh

docker logs -f tcp-server
docker logs -f tcp-client

有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2177198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聚观早报 | 淘宝已接入微信支付;Meta Orion AR眼镜发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 9月29日消息 淘宝已接入微信支付 Meta Orion AR眼镜发布 iQOO 13将登陆印度市场 小鹏汽车加码布局上海 哔哩哔哩…

电脑自带dll修复在哪里,dll丢失的6种解决方法总结

在现代科技日新月异的时代&#xff0c;电脑已经成为我们生活中不可或缺的一部分。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些常见的问题&#xff0c;其中之一就是dll文件丢失或损坏。当这些dll文件丢失或损坏时&#xff0c;可能会导致某些应用程序无法…

网络抓包03 - 实践篇

声明&#xff1a; 本文中提及的APK及相关内容仅用于学习和交流目的&#xff0c;不涉及任何商业用途。本文不鼓励或支持任何形式的版权侵犯行为&#xff0c;同时也强调对软件的安全使用。我们尊重和维护开发者的权益&#xff0c;强烈建议读者在使用软件时遵守相关法律法规&#…

烟雾检测算法、明烟明火检测、烟火识别算法

烟火检测是一种基于先进技术的安全监控手段&#xff0c;主要用于及时发现和预防火灾等安全事故。其技术原理和应用领域可以详细阐述如下&#xff1a; 技术原理 烟火检测算法主要依赖于计算机视觉、深度学习以及图像处理技术。具体步骤包括&#xff1a; 1、数据采集与预处理&…

jQuery——css

本文分享到此结束&#xff0c;欢迎大家评论区相互讨论学习&#xff0c;下一篇继续分享jQuery中offset 和 position的学习。

深度学习--------------------------------门控循环单元GRU

目录 门候选隐状态隐状态门控循环单元GRU从零开始实现代码初始化模型参数定义隐藏状态的初始化函数定义门控循环单元模型训练该部分总代码简洁代码实现 做RNN的时候处理不了太长的序列&#xff0c;这是因为把整个序列信息全部放在隐藏状态里面&#xff0c;当时间很长的话&#…

SpringCloud学习记录|day1

学习材料 2024最新SpringCloud微服务开发与实战&#xff0c;java黑马商城项目微服务实战开发&#xff08;涵盖MybatisPlus、Docker、MQ、ES、Redis高级等&#xff09; 学redis讲到微服务就停了&#xff0c;nginx也是。 所以嘛&#xff0c;我终于来到微服务了。 复习MyBatisP…

鸿蒙HarmonyOS开发生态

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

免费分享一套SpringBoot+Vue火车票订票管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue火车票订票管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringbootVue火车票订票管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 传统办法管理信息首先需要花费的时间比较多&…

CEX上币趋势分析:Infra赛道与Ton生态的未来

在当前的加密市场中&#xff0c;CEX&#xff08;中心化交易所&#xff09;上币的选择愈发重要&#xff0c;尤其是对项目方而言。根据 FMG 的整理&#xff0c;结合「杀破狼」的交易所上币信息&#xff0c;显然 Infra 赛道成为了交易所的热门选择&#xff0c;而 Ton 生态也展现出…

相互作用感知的 3D 分子生成 VAE 模型 - DeepICL 评测

DeepICL 是一个基于相互作用感知的 3D 分子生成模型&#xff0c;能够在目标结合口袋内进行相互作用引导的小分子设计。DeepICL 通过利用蛋白质-配体相互作用的普遍模式作为先验知识&#xff0c;在有限的实验数据下也能实现高度的泛化能力。 一、背景介绍 DeepICL 来源于韩国科学…

CHItrans简介--DVM

DVM基础flow 注&#xff1a;上图中&#xff0c;没有画出DVM指令对应的snoop request&#xff0c;相关snp请求如下所示&#xff1a; 对应的snp请求 Non-sync DVM trans flow Sync DVM trans flow Flow Control 后续的说明&#xff0c;参考&#xff1a; CHI协议之DVM操作_dvm r…

MySql语言操作数据库---MySql引擎,数据表,约束,基本查询,条件查询

数据库引擎 作用:引擎决定了数据是如何存在于数据库中的.不同引擎存储结构和特征是不同的. 常见引擎: InnoDB,MyISAM,MemoryMysql引擎操作: 查看支持的引擎: show engines; 给表设置引擎:create table student2(name varchar(20),age int )engine InnoDB; -- todo 展示所有的…

elasticsearch_exporter启动报错 failed to fetch and decode node stats

最近把服务器迁移到了ubuntu系统&#xff0c;结果发现在centos还正常运行的elasticsearch_exporter&#xff0c;用systemd启动后一直报错 failed to fetch and decode node stats 在网上翻了大半年&#xff0c;竟然都无解&#xff01;这种报错&#xff0c;很明显就是你的ES密码…

使用WPF实现一个快速切换JDK版本的客户端工具

发现网上一键切换JDK环境的方法都是在mac或Linux下的&#xff0c;本人主力电脑是Windows&#xff0c;于是看了一下WPF的文档&#xff0c;自己开发了一个客户端。 直接上代码吧&#xff1a; using JavaSwitch.Properties; using Newtonsoft.Json; using System; using System.…

本地IO与远程IO:揭秘工业自动化中的两大关键角色

在工业自动化领域&#xff0c;IO&#xff08;Input/Output&#xff0c;输入/输出&#xff09;模块扮演着至关重要的角色。它们作为连接控制系统与现场设备的桥梁&#xff0c;负责数据的采集与指令的执行。然而&#xff0c;随着技术的不断进步&#xff0c;IO模块也分为本地IO和远…

【百度文心智能体】想开发爆款智能体?来看看黑神话旅游指南 智能体开发流程大揭秘

&#x1f3ac; 博主&#xff1a;鸽芷咕 ⛺️生活的理想&#xff0c;就是为了理想的生活! 前言 2022年到2023年整年度随着 ChatGPT的爆火&#xff0c;“AI 人工智能 智能助手”概念开始引起各行各业的广泛关注&#xff0c;一些曾经存在于科幻片中的智能助手&#xff0c;到如今也…

探索SpringBoot:学科竞赛管理项目开发

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

从零预训练一个tiny-llama#Datawhale组队学习Task2

完整的教程请参考&#xff1a;datawhalechina/tiny-universe: 《大模型白盒子构建指南》&#xff1a;一个全手搓的Tiny-Universe (github.com) 这是Task2的学习任务 目录 Qwen-blog Tokenizer&#xff08;分词器&#xff09; Embedding&#xff08;嵌入&#xff09; RMS …

Wed前端--HTML基础

目录 一、开发工具 二、HTML文档结构 2.1头部head 2.1.1title标记 2.1.2元信息meta标记 具体实例 ​编辑 一、开发工具 最基础的开发工具是&#xff1a;HBuilder 二、HTML文档结构 HTML文档由头部head和主体body组成 头部head标记中可以定义标题样式&#xff0c;头部信…