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

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

写在前

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

路由器是三层转发-->在网络层转发。【需要解析出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客户端服务器执行结果

相关文章:

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

写在前 简单描述一下关于路由器的三层转发和交换机的二层转发。 路由器是三层转发-->在网络层转发。【需要解析出IP协议中的源IP、目的IP来规划路径】 交换机是二层转发-->在数据链路层转发。【只需要关注下一步发展到哪个相邻的设备上,不需要IP地址&#…...

ChatGPT/GPT4科研技术与AI绘图及论文高效写作

2023年我们进入了AI2.0时代。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车,就有可能被淘汰在这个数字化时代,如何能高效地处理文本、文献查阅、PPT…...

机器学习笔记 - 特斯拉的占用网络简述

一、简述 ​ 2022 年,特斯拉宣布即将在其车辆中发布全新算法。该算法被称为occupancy networks,它应该是对Tesla 的HydraNet 的改进。 自动驾驶汽车行业在技术上分为两类:基于视觉的系统和基于激光雷达的系统。后者使用激光传感器来确定物体的存在和距离,而视觉系统…...

Elesticsearch使用总结

写在前面 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于[云计…...

Node.js--》简易资金管理系统后台项目实战(后端)

今天开始使用 node vue3 ts搭建一个简易资金管理系统的前后端分离项目,因为前后端分离所以会分两个专栏分别讲解前端与后端的实现,后端项目文章讲解可参考:前端链接,我会在前后端的两类专栏的最后一篇文章中会将项目代码开源到我…...

执行autoreconf -fi的过程报错

https://xie.infoq.cn/article/6bba9dd34fb49b7adacb4aacd https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version curl配置quiche的过程中报错, configure:7902: error: possibly undefined macro: AC_LIBTOOL_WIN32_DLLIf this token and ot…...

GPT-3 内幕机制可视化解析

GPT-3 内幕机制可视化解析 GPT-3是一个基于Transformer的语言模型,通过不同的层次提取语言不同层面的特性,构建整个语言的语义信息,它学习的过程跟人类正常学习的过程是类似的,开始的时候是一个无监督预训练,如图5-5所示,GPT-3模型可以将网络上的所有文档下载下来,包含 …...

Linux命令行安装图形化界面

Linux命令行安装图形化界面 安装CentOS默认安装没有配置图形化界面,如何在命令行进行安装图形化界面? 首先要以root用户登录,输入用户名和密码。 切换root用户命令: su root ​ 查看ip地址和网卡编号。 ip addr show 知道网卡编号…...

Rust逆向学习 (2)

文章目录 Guess a number0x01. Guess a number .part 1line 1loopline 3~7match 0x02. Reverse for enum0x03. Reverse for Tuple0x04. Guess a number .part 20x05. 总结 在上一篇文章中,我们比较完美地完成了第一次Rust ELF的逆向工作,但第一次编写的R…...

Flink部署模式及核心概念

一.部署模式 1.1会话模式(Session Mode) 需要先启动一个 Flink 集群,保持一个会话,所有提交的作业都会运行在此集群上,且启动时所需的资源以确定,无法更改,所以所有已提交的作业都会竞争集群中…...

Pytorch公共数据集、tensorboard、DataLoader使用

本文将主要介绍torchvision.datasets的使用,并以CIFAR-10为例进行介绍,对可视化工具tensorboard进行介绍,包括安装,使用,可视化过程等,最后介绍DataLoader的使用。希望对你有帮助 Pytorch公共数据集 torc…...

【第三天】C++类和对象进阶指南:从堆区空间操作到友元的深度掌握

一、new和delete 堆区空间操作 1、new和delete操作基本类型的空间 new与C语言中malloc、delete和C语言中free 作用基本相同 区别: new 不用强制类型转换 new在申请空间的时候可以 初始化空间内容 2、 new申请基本类型的数组 3、new和delete操作类的空间 4、new申请…...

【PyTorch实战演练】自调整学习率实例应用(附代码)

目录 0. 前言 1. 自调整学习率的常用方法 1.1 ExponentialLR 指数衰减方法 1.2 CosineAnnealingLR 余弦退火方法 1.3 ChainedScheduler 链式方法 2. 实例说明 3. 结果说明 3.1 余弦退火法训练过程 3.2 指数衰减法训练过程 3.3 恒定学习率训练过程 3.4 结果解读 4. …...

app拉新渠道整合 一手地推、网推拉新平台整理

1.聚量推客 聚量推客自己本身是服务商,自己直营的平台,相对来说数据更好,我们也拿到了平台首码:000000 填这个就行,属于官方渠道 2.蓝猫推客 蓝猫推客我认为是比较又潜力的平台,经过几天测试数据和结算都…...

十六进制IP转换点分十进制代码

以下是一个可以实现将输入的十六进制格式的IP地址转换为点分十进制格式并输出的简单程序。它使用了 sscanf 函数将输入的字符串解析成无符号整数&#xff0c;然后使用 inet_ntoa 函数将其转换成点分十进制格式&#xff0c;并打印输出&#xff1a; #include <stdio.h> #i…...

面试官的一句话,让五年功能测试老手彻夜难眠!

小王是一名软件测试工程师&#xff0c;已经在目前的公司做了四五年的功能测试。虽然一直表现得非常努力&#xff0c;但他还是没能躲过裁员。只能被动跳槽&#xff0c;寻找更好的职业机会。 然而事情并没有像他想象中那样顺利。在多次面试中小王屡屡碰壁&#xff0c;被面试官吐槽…...

向量检索库Milvus架构及数据处理流程

文章目录 背景milvus想做的事milvus之前——向量检索的一些基础近似算法欧式距离余弦距离 常见向量索引1&#xff09; FLAT2&#xff09; Hash based3&#xff09; Tree based4&#xff09; 基于聚类的倒排5&#xff09; NSW&#xff08;Navigable Small World&#xff09;图 向…...

【华为路由器】配置企业通过5G链路接入Internet示例

场景介绍 5G Cellular接口是路由器用来实现5G技术的物理接口&#xff0c;它为用户提供了企业级的无线广域网接入服务&#xff0c;主要用于eMBB场景。与LTE相比&#xff0c;5G系统可以为企业用户提供更大带宽的无线广域接入服务。 路由器的5G功能&#xff0c;可以实现企业分支…...

python安装.whl文件

python --version https://www.lfd.uci.edu/~gohlke/pythonlibs/ 用CtrlF找需要安装的包 下载对应版本的whl python3.8 把下载好的whl放到安装路径下&#xff1a;C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages 并在该路径下打开cmd执行…...

Java方法调用动态绑定(多态性)详解

CONTENTS 1. 方法调用绑定2. 尝试重写Private方法3. 字段访问与静态方法的多态4. 构造器内部的多态方法行为 1. 方法调用绑定 我们首先来看下面这个例子&#xff1a; package com.yyj;enum Tone {LOW, MIDDLE, HIGH; }class Instrument {public void play(Tone t) {System.ou…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...