JAVAEE初阶相关内容第十五弹--网络編程

news2024/11/20 2:38:10

写在前

简单描述一下关于路由器的三层转发和交换机的二层转发。

路由器是三层转发-->在网络层转发。【需要解析出IP协议中的源IP、目的IP来规划路径】

交换机是二层转发-->在数据链路层转发。【只需要关注下一步发展到哪个相邻的设备上,不需要IP地址,在数据链路层。有一个mac地址。】

这一部分开始进行网络部分的内容,涉及到编程相关的知识,好好学习!!

本篇博客主要是对网络编程进行初步的了解,socket的理解,学习相关API、完成客户端、服务器的【回显服务器】代码编写,在同一台主机上完成通信。

目录

写在前

1.网络编程基础

1.1什么是网络编程

1.2常见的客户端服务端模型

2.Socket套接字

2.1概念

2.2分类

2.2.1流套接字-TCP

2.2.2数据报套接字-UDP

2.3Java数据报套接字通信模型

2.4UDP数据报套接字编程

2.4.1DatagramSocket API

2.4.2DatagramPacket API

2.4.3InetSocketAddress API

2.4.4服务器代码实现

核心思想:

代码实现:

加注释版本:

需要强调的内容:

​2.4.5客户端代码实现

核心思想:

代码实现:

加注释版本:

理解服务器与客户端端口:

2.4.6服务器和客户端执行顺序:

2.4.7IDEA多个客户端设置操作

2.4.8客户端服务器执行结果


1.网络编程基础

1.1什么是网络编程

网络编程,指网络上的主机,通过不同的进程,【只要满足不同的进程就行,所以即便是同一个主机,只要是进程不同,基于网络来传输数据,也属于网络编程。】以编程的方式实现网络通信(或称为网络数据传输。)

1.2常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是指提供用户服务的程序。

(1)客户端先发送请求到服务端。

(2)服务端根据请求数据,执行相应的业务处理。

(3)服务端返回响应,发送业务处理结果。

(4)客户端根据响应数据,展示处理结果(战术获取的资源,或提示保存资源的处理结果)

2.Socket套接字

2.1概念

Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本单元。基于Socket套接字的网络程序开发就是网络编程。

【socket 英文原意为:插座。socket是操作系统给应用程序提供的网络编程的API,可以认为socket API是和传输层密切相关的,传输层里提供了两个核心的协议:TCP和UDP。所以socket api提供了两种风格TCP和UDP  准确的讲有三种unix域套接字,几乎没人用】

2.2分类

一些解释:

可靠传输:网络环境是天然复杂的。不可能保证传输的百分百到达,可靠传输指的是发送方能知道自己的消息发过去了。

是否是可靠传输与是否有无连接没有关系:例如在一些聊天软件上的“已读”功能,是无连接的可靠传输。

全双工半双工:一个通信通道可双向传输(既可以发送也可以接收),就是全双工;一根水管只能单项传输,叫做半双工。TCP/UDP都是全双工是因为一根网线中有八根线

2.2.1流套接字-TCP

TCP,Transmission Control Protocol(传输控制协议),传输层协议。

特点:有连接,可靠传输,面对字节流,有接收缓冲区也有发送缓冲区,大小不限,全双工。

类似于打电话,打电话就是有连接的,需要连接建立才能通信。连接建立需要对方“接受”,如果连接没建立好,则不能进行通信。

对于字节流来说,可以简单地理解为,传输数据是基于IO流的,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

2.2.2数据报套接字-UDP

UDP,User Datagram Protocol(用户数据报协议),传输层协议。

特点:无连接,不可靠传输,面向数据报,有接受缓冲区无发送缓冲区,大小受限:一次最多传输64K,全双工。

类似于发微信,

对于数据报来说,可以简单理解为,传输数据是一块一块的,发送一块数据假如有100个字节,必须一次发送,接收的也必须是100个字节,而不能分100次,每次接收一个字节。

拓展:关于网速快慢

“木桶原理” 在网络通信的过程中有很多路由器、交换机。转发能力存在上限,转发的不止是一个用户的数据。某个设备达到转发能力的上限,就会卡顿丢包。

2.3Java数据报套接字通信模型

对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次会发送全部数据报。一次接收全部数据报。

Java中使用UDP协议通信,主要基于DatagramSocket类来创建数据报套接字,并使用DatagramPacket作为发送或接收的UDP数据报,对于一次发送及接收UDP数据报的流程如下:

以上只是一次发送端的UDP数据报发送,及接收端的数据报接收,并没有返回的数据,也就是只有请求,没有响应。对于一个服务器来说,重要的是提供多个客户端的请求及响应。

下面实现一个最简单的UDP版本的客户端服务器程序--回显服务器(echo serve)

2.4UDP数据报套接字编程

一个普通的服务器:收到请求,根据请求计算响应,返回响应。

echo serve:省略了其中的”根据请求计算响应“,请求是啥,就返回啥(这个代码没有实际的业务,也没有太大作用和意义,只是为了展示socket api 基本用法),但是对于一个服务器来说,一定”根据请求计算响应“这个环节是最重要的。

2.4.1DatagramSocket API

使用这个类表示一个socket对象。【在操作系统中,把socket对象也是当作一个文件来处理的,相当于是文件描述符表中的一项】普通文件对应硬盘设备;socket文件对应网卡。

1个socket对象就可以和另外一台主机进行通信,如果需要多个不同主机通信,则需要创建多个socket对象。

DatagramScocket是UDP Socket,用于发送和接收UDP数据报。

socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。

数据报(Data gram),通过网络传输的数据的基本单元,包含一个报头(header)和数据本身,其中报头描述了数据的目的地以及和其它数据之间的关系。 完备的、独立的数据实体,该实体携带要从源计算机传递到目的计算机的信息,该信息不依赖以前在源计算机和目的计算机以及传输网络间交换。   

DatagramSocket构造方法

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务器)
DatagramSocket方法
方法签名方法说明

void receive(DatagramPacket p) 

此处传入的相当于是一个空对象,receive方法内部,会对参数的这个空对象进行内容填充,从而构造出结果数据,参数也是一个”输出型参数“

从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(Datagram Packet p)从此套接字发送数据报(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

2.4.2DatagramPacket API

DatagramPacket是UDP Socket发送和接收的数据报,表示UDP中传输的一个报文。

DatagramPacket构造方法
方法签名方法说明

DatagramPacket(byte buf ,int length)

把buf这个缓冲区给设置进去了

构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)

DatagramPacket(byte[ ] buf,int offset,int length,SocketAddress address)

Socket Address Ip端口号

构造一个DatagramSocketPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号。

DatagramPacket方法
方法签名方法说明
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址。
int getPort()

从接收端的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号。

byte[ ] getData()获取数据报中的数据

构造UDP发送的数据时,需要传入socketAddress,该对象可以使用InetSocketAddress来创建。

2.4.3InetSocketAddress API

InetSocketAddress(Socket Address 的子类)构造方法
方法签名方法说明
InetSocketAddress(InetAddress addr,int port)创建一个Socket地址,包含IP地址和端口号。

2.4.4服务器代码实现

核心思想:

(1)读取请求并解析

(2)根据请求计算响应

(3)构造响应并写回给客户端

数据到达网卡,经过内核的层层分用,最终到达UDP传输层协议。

调用receive相当于执行到内核中的相关udp代码,就会把这个udp数据报里面载荷部分取出来,拷贝到用户提供的byte[ ]数组中。

代码实现:
package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;


//UDP版本的回显服务器
public class UdpEcSe {
   
    private DatagramSocket socket = null;

    public  UdpEcSe(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
  
    public void start() throws IOException {
        System.out.println("服务器启动!");
       
        while (true){
            
            //1.读取客户端发来的请求是啥
           
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);//通过receive方法来读取请求,receive内部会针对参数对象填充数据。填充的数据来自于网卡
          
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());

            //2.根据请求计算响应,此处是一个回显服务器,所以请求和响应是相同的
            String response = process(request);

            //3.将响应写回客户端,需要用到send方法
           
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());

            socket.send(requestPacket);
            //4.打印一下,当前这次请求响应的处理中间结果

            System.out.printf("[%s:%d] req: %s;resp:%s\n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }

   
    public String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEcSe server = new UdpEcSe(9090);
        server.start();
    }

}
加注释版本:
package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 苏西西
 * Date: 2023-10-18
 * Time: 14:59
 */
//UDP版本的回显服务器
public class UdpEcSe {
    //首先需要创建一个成员
    //网络编程首先是要操作网卡,网卡不方便直接操作
    // 在操作系统内核中使用了一种特殊的叫做“socket”这样的文件来抽象表示网卡
    //因此进行网络通信需要先有一个对象
    private DatagramSocket socket = null;

    //构造方法将对象实例化
    //对于服务器来说,创建的同时还需要关联上一个端口号
    //服务器是网络传输中被动的一方,如果是操作系统随机分配的端口,
    public  UdpEcSe(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    //启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动!");
        //服务器不是只给一个客户端提供服务,需要去服务很多客户端
        while (true){
            //只要有客户端过来就可以提供服务
            //1.读取客户端发来的请求是啥
            //对于UDP来说,传输数据的基本单位是DatagramPacket
            //receive方法的参数是一个输出型参数,需要先构造好一个空白的DatagramPacket对象交给receive 来进行填充
            //DatagramPacket相当于是在点餐的时候给顾客一个空白的纸条,客户写完之后商家再根据纸条的需求来做食物
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);//通过receive方法来读取请求,receive内部会针对参数对象填充数据。填充的数据来自于网卡
            //此时这个DatagramPacket 是一个特殊的对象,并不方便直接进行处理
            //可以将这里包含的数据拿出来构造一个字符串
            //字节数组作为存储数据的缓冲区,此处给的最大的长度是4096,但是这里的空间不一定会被用满,可能只使用小部分
            //因此构造字符串,哪些用了构造那部分,就可以通过getLength获取到实际的数据报的长度
            //只把这个实际有效部分给构造成字符串即可
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());

            //2.根据请求计算响应,此处是一个回显服务器,所以请求和响应是相同的
            String response = process(request);

            //3.将响应写回客户端,需要用到send方法
            // send的参数也是一个DatagramPacket,需要将这个对象构造好
            //这里也需要通过字节数组进行构造,不同的是读请求是需要构造一个空的字节数组
            //读响应的字节数组就不能是空的了,得带有respose里面的内容--响应内容
            //需要注意的是response.getBytes().length是计算字节的个数,这里不能写作response.length() 【字符的个数】
            //DatagramPacket只认字节不认字符。
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());

            socket.send(requestPacket);
            //4.打印一下,当前这次请求响应的处理中间结果
            System.out.printf("[%s:%d] req: %s;resp:%s\n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }

    //根据请求计算响应
    //如果不是回显服务器,则可以在process中灵活的进行处理!!
    public String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        //端口号指定,可以在1024->65535范围内随便挑一个数字!
        UdpEcSe server = new UdpEcSe(9090);
        server.start();
    }

}
需要强调的内容:

2.4.5客户端代码实现

核心思想:

(1)从控制台读取一个要发送的数据       
(2)把这个数据构造成一个UDP的请求并发送
(3)读取服务器的 UDP 响应,并解析           
(4)把解析好的结果显示出来

代码实现:
package network;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;


//UDP版本的回显客户端
public class UdpEcCl {

   
    private DatagramSocket socket = null;
    private String serverIp = null;
    private int serverPort = 0;

   
    public UdpEcCl(String serverIp,int serverPort) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }
    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true){
            //1.从控制台读取一个要发送的数据
            System.out.print(">");
           
            String request = scanner.next();
          
            if(request.equals("exit")){
                System.out.println("bye");
                break;
            }

            //2.把这个数据构造成一个UDP的请求并发送
            
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);

            //3.读取服务器的 UDP 响应,并解析
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);

            //4.把解析好的结果显示出来
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }
      public static void main(String[] args) throws IOException {
        UdpEcCl  clinet = new UdpEcCl("127.0.0.1",9090);
        clinet.start();
    }

}
加注释版本:
package network;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;


//UDP版本的回显客户端
public class UdpEcCl {
    //1.首先需要创建出来一个socket对象
    //网络编程需要操控网卡,就需要创建一个socket对象进行远程操控
    private DatagramSocket socket = null;
    //需要将ip和端口存一下
    private String serverIp = null;
    private int serverPort = 0;

    //写一个构造方法
    //指定服务器的ip和服务器的端口;一次通信需要有俩ip,俩端口
    //客户端的ip是127.0.0.1;端口是系统自动分配的
    //服务器的ip和端口也需要告诉客户端,才能顺利将消息发给服务器
    public UdpEcCl(String serverIp,int serverPort) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }
    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true){
            //1.从控制台读取一个要发送的数据
            System.out.print(">");
            //客户端发送的请求
            String request = scanner.next();
            //对客户端输入的内容进行进行简单的翻译
            if(request.equals("exit")){
                System.out.println("bye");
                break;
            }

            //2.把这个数据构造成一个UDP的请求并发送
            //构造这个packet的时候,需要把serverIp和port都传入过来
            // 但是由于此处的ip地址需要填写的是32位的整数形式
            //上述的IP地址是一个字符串,需要使用  InetAddress.getByName()来进行转换
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);

            //3.读取服务器的 UDP 响应,并解析
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);

            //4.把解析好的结果显示出来
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }
      public static void main(String[] args) throws IOException {
        UdpEcCl  clinet = new UdpEcCl("127.0.0.1",9090);
        clinet.start();
    }

}
理解服务器与客户端端口:

对于服务器来说,端口必须是确定好的,对于客户端来说,端口是可以系统分配的。

来食堂买饭,商家给顾客的小票就相当于是端口号(小票上的编号究竟是多少,也是想当于是随机的,控制不了。就想在客户端这里手动指定端口是可行的,但是并不推荐这样。有可能指定的这个号码会被别人用了。)

客户端如果显示指定端口,就有可能和客户端电脑上的其他程序的端口就冲突了,这一冲突就可能会导致程序没有办法正常通信了。

那么为什么服务器这边指定的端口不怕重复呢?

服务器是程序员自己手里的机器,上面运行什么都是程序员可控的,程序员就可以安排哪个程序使用哪个端口,客户端的机器是在用户的手里,上面运行的程序也是不同的,是不可控的。

2.4.6服务器和客户端执行顺序:

一定是服务器先运行。服务器是被动的一方(类比于我们要去餐馆吃饭,一定是饭店先开门,才能去吃饭。)

第一步,服务器执行到receive进行阻塞。

第二步,客户端执行,客户端读取用户输入的内容。

第三步,客户端发送请求。

第四步,客户端等待响应。服务器收到请求,进行返回。【可以认为这两部分相同的时间执行的】

第五步,服务器根据请求计算响应。process

第六步,服务器执行send,返回响应。

第七步,客户端receive,从阻塞中返回,读到响应

对于客户端服务器程序来说,一个客户端要给很多个服务器提供服务,也就需要构造出多个客户端来进行测试。

2.4.7IDEA多个客户端设置操作

2.4.8客户端服务器执行结果

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

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

相关文章

人工智能发展与结构科学

人工智能(AI)在各种应用中的影响力不断增强,从简单的计算任务到复杂的决策支持。但在这背后,AI的发展其实是一个关于结构演变的故事。从最早的线性结构,到今天的复杂网络结构,结构的演变对AI的能力和效率产…

【离线/并查集】CF1213 G

想起来好久没写题解了,随便写一下把 感觉写多了div3后面的题就变得简单了,div3似乎没什么思维含量,甚至有时候能开出div3的2100.... 心血来潮写一下这个*1800的题解,思路一下就出了,但是一开始多了个log被卡了&#x…

C#通过Entity Framework实体对数据表增删改查

目录 一、创建实体数据模型 1.建立数据库连接 2.建立EF实体模型 二.设计窗体和EF应用 1.窗体设计 2.应用程序设计 3.源码 4.生成效果 (1)查询 (2)修改 (3)删除 (4)增加 …

Python 文件打包成可执行文件

打包 要将Python脚本打包成可执行文件,常见的做法是使用PyInstaller或cx_Freeze工具。下面是使用PyInstaller的基本步骤: 使用conda安装pyinstaller (建议) conda install -c conda-forge pyinstaller上面的命令从conda-forge通…

基于nodejs+vue 衣服穿搭推荐系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…

sd卡的坏块管理与负载均衡

坏块管理 坏块是指在存储介质中出现物理损坏或不可靠的数据块。由于SD卡使用的是闪存技术,它也面临着坏块的问题。 SD卡通过实现坏块管理机制来处理坏块。具体的坏块管理方法可能因制造商和产品型号而有所不同,但通常会采取以下策略: 坏块标…

打卡go学习第一天

8.1 下面展示一些 代码。 package mainimport ("fmt""net""os""time" )type Clock struct {Name stringAddr string } func main() {clocks : []Clock{{Name: "New York", Addr: "localhost:8000"…

笔记39:在Pycharm中为项目添加新解释器

很久不用pycharm都生疏了 a a a 第一步:创建虚拟环境 略 a a a 第二步:将虚拟环境应用到项目中去 【File】----【Settings】----【Project:~~~】-----【Project Interpreter】----【选择合适的解释器】 ​​​​​​​ 因为我们要用新的解释…

【OpenCV概念】 11— 对象检测

一、说明 这都是关于物体识别的。物体识别是指通过计算机视觉技术,自动识别图像或视频中的物体及其属性和特征,是人工智能领域的一个分支。物体识别可应用于多个领域,包括工业自动化、智能家居、医疗、安防等。请随时阅读这篇文章&#xff1a…

摩尔信使MThings的实时数据曲线

摩尔信使MThings配备了毫秒级的实时数据录波功能,提供了多种展示模式,包括:固定时间范围、示波器等; 用户可以添加实时数据警戒线,直观呈现异常数据; 用户可以灵活的缩放、拖动曲线数据,可以指…

nodejs+vue衣服穿搭推荐系统-计算机毕业设计

模块包括主界面,系统首页、个人中心、用户管理、风格标签管理、衣服分类管理、衣服穿搭管理、服装信息管理、我的搭配管理、用户反馈、系统管理等进行相应的操作。无论是日常生活,还是特定场景,诸如面试、约会等,人们都有展现自我…

【试题028】C语言关于逻辑与的短路例题

1.题目&#xff1a;设inta1,b;&#xff0c;执行b0&&(a);后&#xff0c;变量a的值是&#xff1f; 2.代码解析&#xff1a; #include <stdio.h> int main() {//设inta1,b;执行b0&&(a);后&#xff0c;变量a的值是?int a 1, b;printf("表达式的值是…

【每日一题】根据规则将箱子分类

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;分类讨论 其他语言cpython3 写在最后 Tag 【分类讨论】【2023-10-20】 题目来源 2525. 根据规则将箱子分类 题目解读 题目意思明确&#xff0c;根据条件判断箱子的类别。 解题思路 方法一&#xff1a;分类讨论 根据…

Pyqt组合控件与QSpacerItem指南

Pyqt组合控件与QSpacerItem指南&#xff09; 组合控件效果如下所示&#xff1a; QSpacerItem详解 组合控件 创建一个组合的控件&#xff0c;比如 QCheckBox 和 QLabel&#xff0c;并为这个组合设置背景颜色&#xff0c;可以将它们放在一个容器小部件中&#xff0c;然后为容器小…

Leetcode——数组的旋转

189. 轮转数组 class Solution { public:void rotate(vector<int>& nums, int k) {int lennums.size();vector<int> num(len);for(int i0;i<len;i){num[(ik)%len]nums[i];}nums.assign(num.begin(),num.end());} };旋转数组 没看出数学公式gg 正确答案 cl…

经典文献阅读之--Calib Anything(使用SAM的无训练标定雷达相机外参)

0. 简介 Camera与LiDAR之间的外部标定研究正朝着更精确、更自动、更通用的方向发展&#xff0c;由于很多方法在标定中采用了深度学习&#xff0c;因此大大减少了对场景的限制。然而&#xff0c;数据驱动方法具有传输能力低的缺点。除非进行额外的训练&#xff0c;否则它无法适…

安卓Ampere Pro(充电评测)v4.09解锁专业版,供大家学习研究参考!

软件功能 支持查看充电的状态&#xff0c;充电速度是否正常&#xff0c;都可以轻松测试。 强大的测试功能&#xff0c;让你全面了解充电的状态。 温度过高提醒&#xff0c;保证手机的温度不过高&#xff0c;及时拔掉电源。 设置通知优先级&#xff0c;最高、较高、默认、较…

Zookeeper集群 + Kafka集群的详细介绍与部署

文章目录 1. Zookeeper 概述1.1 简介1.2 Zookeeper的工作机制1.3 Zookeeper 主要特点1.4 Zookeeper 数据结构1.5 Zookeeper的相关应用场景1.5.1 统一命名服务1.5.2 统一配置管理1.5.3 统一集群管理1.5.4 服务器动态上下线1.5.5 软负载均衡 1.6 Zookeeper 选举机制1.6.1 第一次启…

SI基础知识:说一说玻纤布规格(如1078)的具体含义,以及等效Dk计算

玻纤布的编织包含经向和纬向两个不同的方向&#xff0c;这些玻璃布并没有被紧密放置在一起&#xff0c;在玻纤布上会有开窗&#xff0c;而且经向开窗和纬向开窗大小不同。 IPC定义了每种玻纤布的编织密度以及所用玻璃丝的规格&#xff0c;如下图所示。 看上面的表格&#xff0c…

Fast DDS之Subscriber

目录 SubscriberSubscriberQosSubscriberListener创建Subscriber DataReaderSampleInfo读取数据 Subscriber扮演容器的角色&#xff0c;里面可以有很多DataReaders&#xff0c;它们使用Subscriber的同一份SubscriberQos配置。Subscriber可以承载不同Topic和数据类型的DataReade…