java之网络编程篇
前言
网络编程就是计算机和计算机之间通过网络进行数据传输,下面介绍一些概念和如何实现UDP和TCP两种模式的传输。
一、常见的软件架构C/S和B/S
C/S架构需要一个客户端软件程序+服务器
B/S只需要打开网页+服务器
C/S架构的优缺点和应用场景
优点:画面可以做的非常精美,用户体验好
缺点:需要开发客户端,也需要开发服务端
用户需要下载和更新的时候太麻烦
应用场景:适合定制专业化的办公类软件如:IDEA、网游
B/S架构的优缺点和应用场景
优点:不需要开发客户端,只需要开发服务端
用户不需要下载,打开浏览器就能使用
缺点:如果应用过大,用户体验受到影响
应用场景:适合移动互联网应用,可以在任何地方随时访问的系统。
二、网络编程三要素(IP、端口号、协议)
1.概述
IP 设备在网络中的地址,是唯一的标识。
端口号 应用程序在设备中唯一的标识。
协议 数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。
2.详说
IP
全称:Internet Protocol,是互联网协议地址,也称IP地址。
是分配给上网设备的数字标签。
通俗理解就是,上网设备在网络中的地址,是唯一的
常见的IP分类为 IPv4、IPv6
为解决IPv4的IP不够用的问题,出现了IPv6
IPv4的细节
分类:公网地址(万维网使用)和私有地址(局域网使用)。
192.168.开头的就是私有址址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用,以此节省IP
三个问
1.IPv6还未普及,现在如何解决IPv4不够的问题?
利用局域网IP解决IP不够的问题
2.特殊的IP是什么?
127.0.0.1(永远表示本机)
3.常见的两个CMD命令
ipconfig:查看本机IP地址
ping:检查网络是否连通
InetAddress类
InetAddress类可以获取IP对象,主机名,IP
public class InetAddressTest {public static void main(String[] args) throws UnknownHostException {//传递电脑的名字或网址都可以获得对应的IP地址InetAddress address = InetAddress.getByName("LAPTOP-8DV5B4U6");System.out.println(address);//获得本机的主机名String hostName = address.getHostName();System.out.println(hostName);//获得本机的IP地址String hostAddress = address.getHostAddress();System.out.println(hostAddress);} }
端口号
就是,应用程序在设备中唯一的标识。
端口号:由两个字节表示的整数,取值范围:0~65535
其中0~1023之间的端口号用于一些知名的网络服务或者应用。
我们自己使用1024以上的端口号就可以了。
注意:一个端口号只能被一个应用程序使用。
传输的数据只能由电脑绑定的端口号的端口发出和接收
协议
计算机网络中,连接和通信的规则被称为网络通信协议。
下面是传输层的两个协议UDP和TCP
三、UDP
1.发送数据
步骤
(1)创建发送端的DatagramSocket对象
(2)数据打包(DatagramPacket)
(3)发送数据
(4)释放资源
示例代码
public class SendDataTest {public static void main(String[] args) throws IOException {//1.创建UDP socket 即new 一个 DatagramSocket对象//细节://绑定端口,以后我们就是通过这个端口往外发送//空参:所有可用的端口中随机一个进行使用//带参:指定端口进行绑定DatagramSocket socket = new DatagramSocket();//2.打包数据byte[] data = "你好厉害u".getBytes();InetAddress address = InetAddress.getByName("127.0.0.1");int port = 10086;DatagramPacket packet = new DatagramPacket(data, data.length, address, port);//3.发送数据socket.send(packet);//关闭资源socket.close();} }
2.接收数据
步骤
(1)创建接收端的DatagramSocket对象
(2)接收打包好的数据(DatagramPacket)
(3)解析数据包
(4)释放资源
示例代码
public class ReceiveDataType {public static void main(String[] args) throws IOException {// 1.创建一个DatagramSocket对象//细节://在接收的时候,一定要绑定端口//而且绑定的端口一定要跟发送的端口保持一致DatagramSocket socket = new DatagramSocket(10086);// 2.创建一个DatagramPacket对象接收数据byte[] bytes = new byte[1024];DatagramPacket packet = new DatagramPacket(bytes,bytes.length);//该方法是阻塞的//程序执行到这一步的时候,会在这里死等//等发送端发送消息socket.receive(packet);//3.解析数据byte[] data = packet.getData();int len = packet.getLength();String str = new String(data,0,len);InetAddress address = packet.getAddress();int port = packet.getPort();System.out.println("接收到的数据:"+str);System.out.println("这数据从"+address+"这台电脑中的"+port+"端口发出");//关闭资源socket.close();} }
3.聊天室
按照下面的要求实现程序
UDP发送数据:娄数据来自于键盘录入,直到输入的数据是886,发送数据结束
UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
发送端代码
public class SendSide {public static void main(String[] args) throws IOException {DatagramSocket socket = new DatagramSocket();Scanner scanner = new Scanner(System.in);while (true) {System.out.println("请输入要发送的信息:");String s = scanner.nextLine();if ("886".equals(s)){break;}byte[] data = s.getBytes();InetAddress address = InetAddress.getByName("127.0.0.1");int port = 10086;DatagramPacket packet = new DatagramPacket(data, data.length, address, port);socket.send(packet);}socket.close();} }
idea里面修改发送代码的运行配置,改为允许多个实例跑
接收端代码
public class ReceiveSide {public static void main(String[] args) throws IOException {DatagramSocket socket = new DatagramSocket(10086);byte[] data = new byte[1024];DatagramPacket packet = new DatagramPacket(data, data.length);while (true) {socket.receive(packet);byte[] data1 = packet.getData();int length = packet.getLength();String str = new String(data1, 0, length);SocketAddress socketAddress = packet.getSocketAddress();System.out.println("来自:" + socketAddress+"发出的一条信息:" + str );}} }
4.三种通信方式(单播、组播、广播)
单播 上面的代码就是单薄
组播 组播地址:224.0.0.0~239.255.255.255 发送到的数据一组的主机都能收到
其中224.0.0.0~224.0.0.255为预留的组播地址广播 广播地址:255.255.255.255 发送到的数据所有的主机都能收到
(1)组播
发送数据步骤
1.创建MulticastSocket对象
2.创建DatagramPacket对象(这里的目的ip对象要指定组播地址比如224.0.0.1)
3.调用MulticastSocket发送数据方法发送数据
4.释放资源
接收数据步骤
1.创建MulticastSocket对象
2.将当前本机,添加到224.0.0.1的这一组当中
3.创建DatagramPacket对象
4.接收数据
5.解析数据
6.释放资源
实例代码
1.发送端代码
public class SendSide {public static void main(String[] args) throws IOException {//1.创建UDP socket 即new 一个 MulticastSocket对象MulticastSocket socket = new MulticastSocket();//2.打包数据byte[] data = "你好厉害u".getBytes();//指定接收端的组播ipInetAddress address = InetAddress.getByName("224.0.0.1");//指定接收端的端口int port = 10086;DatagramPacket packet = new DatagramPacket(data, data.length, address, port);//3.发送数据socket.send(packet);//关闭资源socket.close();} }
2.接收端代码
public class ReceiveSide {public static void main(String[] args) throws IOException {// 1.创建一个MulticastSocket对象//细节://在接收的时候,一定要绑定端口//而且绑定的端口一定要跟发送的端口保持一致MulticastSocket socket = new MulticastSocket(10086);//2..将当前本机,添加到224.0.0.2的这一组当中InetAddress address = InetAddress.getByName("224.0.0.2");socket.joinGroup(address);// 3.创建一个DatagramPacket对象接收数据byte[] bytes = new byte[1024];DatagramPacket packet = new DatagramPacket(bytes,bytes.length);//4.接收数据//该方法是阻塞的//程序执行到这一步的时候,会在这里死等//等发送端发送消息socket.receive(packet);//5.解析数据byte[] data = packet.getData();int len = packet.getLength();String str = new String(data,0,len);InetAddress src = packet.getAddress();int port = packet.getPort();System.out.println("接收到的数据:"+str);System.out.println("这数据从"+src+"这台电脑中的"+port+"端口发出");//6.关闭资源socket.close();} }
设置接收端的代码的运行设置为允许多个实例运行。
多次运行接收端的代码,控制台多几个接收端的实例,几个接收实例创建就加入224.0.0.2的一个组播地址的组。只要发送端一发送消息,几个接收端都能收到。
(2)广播
这个广播只需要在单播的基础上,修改发送端发送包参数指定的目的ip地址。
修改后的发送端代码如下
发送后,无论是多个单播或组播的接收端都是能接收到的。但是端口号还是要对应。
四、TCP
1.客户端和服务端的步骤
2.实例代码
服务端代码
public class ServerType {public static void main(String[] args) throws IOException {//1.创建一个服务器ServerSocketServerSocket serverSocket = new ServerSocket(10086);//2.监听客户端的连接//没有客户端连接,会阻塞在这里Socket socket = serverSocket.accept();//3.获取输入流InputStream inputStream = socket.getInputStream();//4.读数据int b;while ((b = inputStream.read()) != -1) {System.out.print((char) b);}//5.关闭流inputStream.close();socket.close();} }
客户端代码
public class CilentType {public static void main(String[] args) throws IOException {//1.创建客户端socketSocket socket = new Socket("127.0.0.1", 10086);//2.获取输出流OutputStream outputStream = socket.getOutputStream();//3.写数据outputStream.write("我是客户端".getBytes());//4.关闭资源outputStream.close();socket.close();} }
注意:上面的代码是使用字节流传输数据的,中文的话会乱码
因此需要将字节输入流转换为字符输入流,要修改服务端的代码
修改后的服务端的代码
public class ServerType {public static void main(String[] args) throws IOException {//1.创建一个服务器ServerSocketServerSocket serverSocket = new ServerSocket(10086);//2.监听客户端的连接//没有客户端连接,会阻塞在这里Socket socket = serverSocket.accept();//3.获取输入流InputStream inputStream = socket.getInputStream();//转换为字符流,避免出现中文乱码InputStreamReader isr = new InputStreamReader(inputStream);//4.读数据int b;while ((b = isr.read()) != -1) {System.out.print((char) b);}//5.关闭流inputStream.close();socket.close();} }
运行结果正常
3.三次握手和四次挥手
(1)三次握手
(2)四次挥手
五、Demo
1.Demo1 多发多收
客户端代码
public class Client {public static void main(String[] args) throws IOException {//1.创建Socket对象并连接服务端Socket socket = new Socket("127.0.0.1", 10086);Scanner sr = new Scanner(System.in);//2.获取输出流,发送数据OutputStream outputStream = socket.getOutputStream();while (true) {System.out.println("请输入要发送的数据:");String str = sr.nextLine()+"\r\n";if ("886".equals(str)){break;}outputStream.write(str.getBytes());}//3.释放资源outputStream.close();socket.close();} }
服务端代码
public class Server {public static void main(String[] args) throws IOException {//1.创建一个服务器ServerSocketServerSocket serverSocket = new ServerSocket(10086);//2.调用accept()方法,获取到请求的客户端SocketSocket socket = serverSocket.accept();//3.获取输入流,读取客户端发送的数据InputStreamReader isr = new InputStreamReader(socket.getInputStream());int b;while((b = isr.read()) != -1) {System.out.print((char)b);}//4.关闭流和socketisr.close();socket.close();} }
2.Demo2 接收和反馈
客户端代码
public class CilentType {public static void main(String[] args) throws IOException {//1.创建客户端socketSocket socket = new Socket("127.0.0.1", 10086);//2.获取输出流OutputStream outputStream = socket.getOutputStream();//3.写数据outputStream.write("我是客户端".getBytes());//在此写一个结束标记socket.shutdownOutput();//4.接收服务端的回复InputStreamReader isr = new InputStreamReader(socket.getInputStream());int b;while ((b = isr.read()) != -1) {System.out.print((char) b);}//关闭资源outputStream.close();isr.close();socket.close();} }
服务端代码:
public class ServerType {public static void main(String[] args) throws IOException {//1.创建一个服务器ServerSocketServerSocket serverSocket = new ServerSocket(10086);//2.监听客户端的连接//没有客户端连接,会阻塞在这里Socket socket = serverSocket.accept();//3.获取输入流InputStream inputStream = socket.getInputStream();//转换为字符流,避免出现中文乱码InputStreamReader isr = new InputStreamReader(inputStream);//4.读数据int b;//细节://read方法会从连接通道中读取数据//如果客户端没有发送数据,会阻塞在这里//需要一个结束标记,此处循环才会停止。while ((b = isr.read()) != -1) {System.out.print((char) b);}//5.写回数据String str = "我是服务端";socket.getOutputStream().write(str.getBytes());//关闭流inputStream.close();socket.close();} }
注意:
read方法会从连接通道中读取数据
如果客户端没有发送数据,会阻塞在循环那里
需要一个结束标记,循环才会停止。
3.Demo3 上传文件
客户端代码
public class Client {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1", 10086);BufferedInputStream bis = new BufferedInputStream(new FileInputStream("files\\xjj.jpg"));BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());byte[] buffer = new byte[1024];int b;while ((b = bis.read(buffer)) != -1) {bos.write(buffer, 0, b);}bos.flush();socket.shutdownOutput();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = br.readLine();System.out.println(line);socket.close();} }
服务端代码
public class Server {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(10086);Socket socket = serverSocket.accept();BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy\\a.jpg"));int b;byte[] buf = new byte[1024];while ((b = bis.read(buf)) != -1) {bos.write(buf, 0, b);}bos.flush();BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bw.write("服务端接收到了数据!");bw.newLine();bw.flush();socket.close();serverSocket.close();} }
注意注意注意:1.缓冲字节流是需要刷新的 2.流不要随意的关闭,不然就导致socket关闭了
4.Demo4 文件名重复问题
这道代码只需要在上一题的基础上,修改服务端的代码,保存文件的名字用下面的UUID类生成唯一的标识码。
5.Demo5 上传文件多线程版本
使用循环+多线程
服务端代码
public class Server {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(10086);while (true) {Socket socket = serverSocket.accept();MyRunnable mr = new MyRunnable(socket);new Thread(mr).start();}} }
线程类代码
public class MyRunnable implements Runnable{Socket socket;public MyRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());String name = UUID.randomUUID().toString().replace("-", "")+".jpg";BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy\\"+name));int b;byte[] buf = new byte[1024];while ((b = bis.read(buf)) != -1) {bos.write(buf, 0, b);}bos.flush();BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bw.write("服务端接收到了数据!");bw.newLine();bw.flush();} catch (IOException e) {throw new RuntimeException(e);} finally {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}} }
客户端代码(和上面的一样)
public class Client {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1", 10086);BufferedInputStream bis = new BufferedInputStream(new FileInputStream("files\\xjj.jpg"));BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());byte[] buffer = new byte[1024];int b;while ((b = bis.read(buffer)) != -1) {bos.write(buffer, 0, b);}bos.flush();socket.shutdownOutput();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = br.readLine();System.out.println(line);socket.close();} }
6.Demo6 线程池优化版本
在上一道题的代码的基础上,修改服务端的代码,增加一个线程池管理线程
修改后的服务端的代码
public class Server {public static void main(String[] args) throws IOException {//创建自定义线程池ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数10,//最大线程数60,//空闲时间TimeUnit.SECONDS,//时间单位new ArrayBlockingQueue<>(2),//阻塞队列Executors.defaultThreadFactory(),//线程工厂new ThreadPoolExecutor.AbortPolicy()//拒绝策略);ServerSocket serverSocket = new ServerSocket(10086);while (true) {Socket socket = serverSocket.accept();MyRunnable mr = new MyRunnable(socket);threadPoolExecutor.submit(mr);}} }
7.Demo7 接收浏览器的信息并打印
这道题只需要服务端的代码,然后用浏览器去访问服务端
给个Demo1的服务端代码
public class Server {public static void main(String[] args) throws IOException {//1.创建一个服务器ServerSocketServerSocket serverSocket = new ServerSocket(10086);//2.调用accept()方法,获取到请求的客户端SocketSocket socket = serverSocket.accept();//3.获取输入流,读取客户端发送的数据InputStreamReader isr = new InputStreamReader(socket.getInputStream());int b;while((b = isr.read()) != -1) {System.out.print((char)b);}//4.关闭流和socketisr.close();socket.close();} }
先运行服务端的代码,再打开浏览器,输入127.0.0.1:10086访问服务端
服务端在控制台输出
相关文章:

java之网络编程篇
前言 网络编程就是计算机和计算机之间通过网络进行数据传输,下面介绍一些概念和如何实现UDP和TCP两种模式的传输。 一、常见的软件架构C/S和B/S C/S架构需要一个客户端软件程序服务器 B/S只需要打开网页服务器 C/S架构的优缺点和应用场景 优点:画面可以…...

stm32f103c8t6与TB6612FNG解耦测试
stm32f103c8t6与TB6612FNG解耦测试 本文操作方式: 忽略底层,只做上层, 所以前面全部照搬步骤,重在调试 文章目录 stm32f103c8t6与TB6612FNG解耦测试本文操作方式:创建基本工程(1)跳转此链接,创建(2)创建电机驱动文件夹(3)PWM原理(4)电机转动控制 oled调试和key调试(5)OLED转速…...
2253336 - 资源库 - OAC0 中的脱机状态
症状 资源库的状态显示为离线。 环境 SAP 内容服务器 6.50 或更高版本与 MaxDB 存储媒介结合使用对于状态为离线的资源库,测试报表 RSCMST 运行正常资源库可在应用程序中使用,没有任何问题 重现问题 启动事务 OAC0双击资源库按 "CSADMIN"…...

uni-app总结
1. <u-form-item label"报废人" ><u--input v-model"model.remark" border"bottom" placeholder"请输入"></u--input> </u-form-item> border"bottom" 报废日期 为了...

【JavaEE初阶】线程安全的集合类
📕 引言 我们之前讲过的集合类,,大部分都不是线程安全的. Vector, Stack, HashTable, 是线程安全的(都是自带了synchronized,不建议用), 其他的集合类不是线程安全的。 注意:加锁不能保证线程一定安全,不加锁也不能确定线程一定…...

关于Vue项目npm快捷键,点击run启动报错,及npm i也报错的解决办法
1.配置idea的npm 2.点击运行按钮 3.结果 分析原因及问题: npm i npm run dev 由于是刚刚从gitlab新拉的前端代码,可能没有用命令install过类似于没有编译过,所以执行一下上面的命令 结果报错如下: F:\tbyf\qjyy\hip-manager-ui&…...
React中,className属性自定义组件不生效的问题
在React中,className属性不仅适用于原生的HTML元素,也可以用于自定义组件。实际上,className属性是React中通用的属性,可以应用于任何React元素,无论是原生的HTML元素还是自定义的组件。 为什么使用className而不是cl…...
Ubuntu22.04搭建fabric开发环境、开发环境下运行链码
在智能合约开发过程中,开发人员需要一种快速、迭代地测试链码包的方法,而无需为每次修改运行链码生命周期命令。 使用 Fabric 二进制文件并启动peer处于开发模式(“DevMode”),然后将链码连接到peer。它允许您启动链代…...

[BSidesCF 2019]Kookie1
打开题目,看到 根据提示,账号:cookie。密码:monster。试一下登录,登陆成功 抓包看看信息 根据提示, 看一下返回包 账号要加username要改成admin,改一下试试 构造cookie 直接得到flag flag{c…...
LCM红外小目标检测
根据站内的matlab代码修改成python版本。 import numpy as np import matplotlib.pyplot as plt import cv2 from pylab import mpl# 设置中文显示字体 mpl.rcParams["font.sans-serif"] ["SimHei"]def LCM_computation(patch_LCM_in):row, col patch_L…...

振德医疗选择泛微千里聆RPA,助力电商、人事业务流程自动化
振德医疗用品股份有限公司成立于1994年,中国A股上市公司,是医用敷料和感控防护产品主要的供应商之一。 (图片素材来自振德医疗官网) 振德医疗的业务在线上线下齐发力。目前拥有5个国内生产基地,3个海外工厂࿰…...

VBA高级应用30例应用3在Excel中的ListObject对象:创建表
《VBA高级应用30例》(版权10178985),是我推出的第十套教程,教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开,这套教程案例与理论结合,紧贴“实战”,并做“战术总结”,以…...

IP 地址在 SQL 注入攻击中的作用及防范策略
数据库在各个领域的逐步应用,其安全性也备受关注。SQL 注入攻击作为一种常见的数据库攻击手段,给网络安全带来了巨大威胁。今天我们来聊一聊SQL 注入攻击的基本知识。 SQL 注入攻击的基本原理 SQL 注入是通过将恶意的 SQL 代码插入到输入参数中…...
Unity VR黑屏
picosdk里面的,有修改 using System.Collections; using System.Collections.Generic; using UnityEngine;public class ScreenFade : MonoBehaviour {[Tooltip("颜色")]public Color fadeColor new Color(0.0f, 0.0f, 0.0f, 1.0f);private int renderQ…...
Vue.js 中使用 Watcher 的强大场景和案例
目录 表单验证 示例代码: HTML: 获取 API 数据 示例代码: HTML: 深度监听对象变化 示例代码: HTML: 观察多个数据源 示例代码: HTML: Vue.js 是一个流行的前端框架,以其直观的数据绑定和组件驱动的开发模式而闻名。其中,watch 功能是其响应式编程模型…...

《实现 DevOps 平台(2) · GitLab CI/CD 交互》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...

【机器学习sklearn实战】岭回归、Lasso回归和弹性网络
一 sklean中模型详解 1.1 Ride regression 1.2 Lasso regression 1.3 ElasticNet 二 算法实战 2.1 导入包 import numpy as np import pandas as pd from sklearn import datasets from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.linear…...
Python 爬虫项目实战六:抓取猫眼电影排行榜的数据
在这篇博客中,我们将通过一个实际的Python爬虫项目,详细讲解如何抓取网页数据。本次选择的实战项目是抓取猫眼电影排行榜的数据,通过这个项目,你将学会如何使用Python编写爬虫,从网页中提取有用的电影信息。 一、项目…...

YOLO系列:从yolov1至yolov8的进阶之路 持续更新中
一、基本概念 1.YOLO简介 YOLO(You Only Look Once):是一种基于深度神经网络的对象识别和定位算法,其最大的特点是运行速度很快,可以用于实时系统。 2.目标检测算法 RCNN:该系列算法实现主要为两个步骤&…...

欧拉系统离线安装界面ukui
1、官网下载安装镜像iso后,默认没有gui openEuler | 开源社区 | openEuler社区官网openEuler是一个开源、免费的 Linux 发行版平台,将通过开放的社区形式与全球的开发者共同构建一个开放、多元和架构包容的软件生态体系。同时,openEuler 也是…...
PostgreSQL 的扩展pg_freespacemap
PostgreSQL 的扩展pg_freespacemap pg_freespacemap 是 PostgreSQL 提供的一个内置扩展,用于查看表的空闲空间映射(Free Space Map, FSM)信息。这个扩展对于数据库性能调优和空间管理非常有用。 一 扩展概述 功能:提供对表的空…...
Nginx+Tomcat负载均衡与动静分离架构
目录 简介 一、Tomcat基础部署与配置 1.1 Tomcat应用场景与特性 1.2 环境准备与安装 1.3 Tomcat主配置文件详解 1.4 部署Java Web站点 二、NginxTomcat负载均衡群集搭建 2.1 架构设计与原理 2.2 环境准备 2.3 Tomcat2配置(与Tomcat1对称) 2.4…...

机器学习方法实现数独矩阵识别器
目录 导包 工具函数构建说明 1. 基础图像处理工具 2. 图像预处理模块 3. 数独轮廓检测与定位 4. 网格划分与单元格提取 5. 数字特征提取 6. 多网格处理流程 数据流分析 核心算法详解 核心机器视觉方法 1. 透视变换校正算法 2. 数字区域提取算法 3. 多网格检测算法…...
论文阅读:HySCDG生成式数据处理流程
论文地址: The Change You Want To Detect: Semantic Change Detection In Earth Observation With Hybrid Data Generation Abstract 摘要内容介绍 📌 问题背景 “Bi-temporal change detection at scale based on Very High Resolution (VHR) images is crucia…...
《视觉SLAM十四讲》自用笔记 第三讲:三维空间刚体运动
第三讲 三维空间刚体运动 3.0 目标 1.理解三维空间的刚体运动描述方式:旋转矩阵、变换矩阵、四元数和欧拉角。 2.掌握 Eigen 库的矩阵、几何模块使用方法。 3.1 旋转矩阵 3.1.1 点和向量,坐标系 三维空间中,刚体的运动可以用两个概念来…...

PHP环境极速搭建
一、为什么选择phpStudy VS Code? 作为一名初次接触PHP的开发者,我深知环境配置往往是学习路上的第一道门槛。传统PHP环境搭建需要手动配置Apache/Nginx、PHP解释器、MySQL等多重组件,光是处理版本兼容性和依赖问题就可能耗费半天时间——这…...

【MySQL系列】MySQL 执行 SQL 文件
博客目录 一、MySQL 执行 SQL 文件的常见场景二、MySQL 执行 SQL 文件的主要方法1. 使用 MySQL 命令行客户端2. 在 MySQL 交互界面中使用 source 命令3. 使用 MySQL Workbench 等图形化工具4. 使用编程语言接口 三、执行 SQL 文件时的注意事项1. 字符集问题2. 事务处理3. 错误处…...

Spark流水线+Gravitino+Marquez数据血缘采集
1.Openlinage和Marquez简介 1.1 OpenLineage 概述 OpenLineage 是一个开放标准和框架,用于跨工具、平台和系统捕获数据血缘信息。它定义了通用的数据血缘模型和API,允许不同的数据处理工具(如ETL、调度器、数据仓库)以标准化格…...
提取数据区域中表格
查看本示例演示效果本示例关键代码的编写位置,请参考“开始 - 快速上手”里您所使用的开发语言框架的最简集成代码 在实际的开发过程中,有时会遇到希望提取Word文档中表格数据保存到服务器的需求,此时可以使用PageOffice提取Word文档数据区域…...
Rust 学习笔记:使用自定义命令扩展 Cargo
Rust 学习笔记:使用自定义命令扩展 Cargo Rust 学习笔记:使用自定义命令扩展 Cargo Rust 学习笔记:使用自定义命令扩展 Cargo Cargo 支持通过 $PATH 中的 cargo-something 形式的二进制文件拓展子命令,而无需修改 Cargo 本身。 …...