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

由浅到深认识Java语言(39):网络编程

该文章Github地址:https://github.com/AntonyCheng/java-notes

在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

上一章:由浅到深认识Java语言(38):I/O流

45.网络编程

软件结构

**C/S结构:**全称为 Client/Server 结构,是指客户端和服务器结构,重点在于客户端开发,常见的程序有QQ,迅雷,百度网盘等软件,但是客户端开发并不适合于 Java ,而适合于 C/C++ ;

**B/S结构:**全称为 Browser/Server 结构,是指浏览器和服务器结构,重点在于服务器端开发,常见浏览器有 IE ,谷歌,火狐等,服务端开发才是适合用 Java 实现的;

两种架构各有优势,但是无论是哪种架构,都离不开网络的支持;

**网络编程:**就是在一定的协议下,实现两台计算机的通信的程序;

网络通信协议

TCP/IP协议参考模型

  • **网络通信协议:**通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。

  • TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上图中,OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广。

TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。

  • 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
  • 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。而IP协议是一种非常重要的协议。IP(internet protocal)又称为互联网协议。IP的责任就是把数据从源传送到目的地。它在源地址和目的地址之间传送一种称之为数据包的东西,它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求。
  • 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议TCP(Transmission Control Protocol)协议,即传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。UDP(User Datagram Protocol,用户数据报协议):是一个无连接的传输层协议、提供面向事务的简单不可靠的信息传送服务。
  • 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。

而通常我们说的TCP/IP协议,其实是指TCP/IP协议族,因为该协议家族的两个最核心协议:TCP(传输控制协议)和IP(网际协议),为该家族中最早通过的标准,所以简称为TCP/IP协议。

TCP与UDP协议

我们所接触较多的是 TCP 协议,而 UDP 协议了解即可;

java.net 包中提供了两种常见的网络协议的支持:

  • UDP:用户数据报协议(User Datagram Protocol);

    • 面向无连接的,不可靠的且不安全的协议:UDP 是无连接通信协议,即在传输数据时,数据的发送端和接收端不建立逻辑链接,就是一台计算机向另一台计算机发送数据时不会确认接收端是否存在就会发出信息,同样接收端在收到数据时也不会向发送端反馈是否收到数据,==所以容易产生丢包(数据包丢失)的现象==;
    • **消耗资源小,通信效率高:**所以常用于音频,视频和普通数据(QQ,微信消息)的传输,即使丢失一两个数据包也不会对接收结果产生太大影响,但是Java 并不擅长这样的协议
    • **有大小限制:**UDP 协议会把数据限制在 64KB 之内,超出这个范围就不能发送了;
    • **数据报(Datagram):**网络传输的基本单位;
  • TCP:传输控制协议(Transmission Control Protocol);

    • **面向连接的,可靠协议:**通信双方必须建立逻辑链接才能传输数据,理论上此种数据传输是可靠无差错的,往往现实不然,它是基于字节流的传输层通信协议,可以连续传输大量的数据,类似于打电话或者是百度云盘的下载;

    • **握手和挥手:**当一台计算机与另一台计算机建立连接时,TCP 协议会采用“三次握手”方式让它们建立一个连接——用于发送和接收数据虚拟链路,当数据传输完毕后 TCP 协议会采用“四次挥手”的方式断开连接;

      • **三次握手:**TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠,但是会浪费网络资源,速度慢;

        • 第一次握手:客户端向服务器端发出连接请求,等待服务器确认;

          注意:服务器端永远不会向客户端主动发起连接请求;

        • 第二次握手:服务器端向客户端送回一个响应,通知客户端收到了连接请求;

        • 第三次握手:客户端再次向服务器端发出确认信息,确认连接;

      • **四次挥手:**TCP协议中,在发送数据结束后,释放连接时需要经过四次挥手;

        • 第一次挥手:客户端向服务器端提出结束连接,让服务器端做最后的准备工作,此时客户端处于半关闭状态,即不再向服务器端发送数据,但是可以接收数据;

        • 第二次挥手:服务器端收到释放连接的请求后,会将最后的数据发给客户端,并且告知上层应用进程不再接收数据;

        • 第三次挥手:服务器端发送完数据后,会给客户端发送一个释放连接的报文,那么客户端接收后就知道可以正式释放连接了;

        • 第四次挥手:客户端接收到服务器端最后的释放连接报文后,要回复一个彻底断开的报文,这样服务器端收到之后才会彻底释放连接;

网络编程三要素

协议

**协议:**计算机网络通信必须遵守的规则,详情请看上节介绍;

IP地址

IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”;

IP地址分类方式一:

  • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个;

  • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张;

    为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题;

IP地址分类方式二:

公网地址(万维网使用)和 私有地址(局域网使用)。192.168.开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用;

常用命令:

  • 查看本机IP地址,在控制台输入:
ipconfig

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 检查网络是否连通,在控制台输入:
ping 空格 IP地址
ping 192.168.80.1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特殊的IP地址:

  • 本地回环地址(hostAddress):127.0.0.1
  • 主机名(hostName):localhost

域名:

因为IP地址数字不便于记忆,因此出现了域名,域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。 ------- 域名解析;

端口号

网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?

如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了;

  • 端口号:用两个字节表示的整数,它的取值范围是0~65535
    • 公认端口:0~1023。被预先定义的服务通信占用,如:HTTP(80),FTP(21),Telnet(23);
    • 注册端口:1024~49151。分配给用户进程或应用程序。如:Tomcat(8080),MySQL(3306),Oracle(1521);
    • 动态/ 私有端口:49152~65535;

如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败;

利用 协议+IP地址+端口号 三元组合,就可以标识网络中的进程: IP 192.168.1.100:8080 ,那么进程间的通信就可以利用这个标识与其它进程进行交互;

InetAddress类

InetAddress 类获取本机 IP 地址对象;

package top.sharehome.Demo;import java.net.InetAddress;public class Demo {public static void main(String[] args) throws Exception {/*** 以下是该类获取自己计算机的ip地址和主机名*/InetAddress inetAddress = InetAddress.getLocalHost();String ip = inetAddress.getHostAddress();String hostName = inetAddress.getHostName();System.out.println("inetAddress = " + inetAddress);System.out.println("ip = " + ip);System.out.println("hostName = " + hostName);System.out.println("===================================");/*** 以下是该类获取远程计算机的ip地址和主机名*/InetAddress inetAddress1 = InetAddress.getByName("byName");String ip1 = inetAddress1.getHostAddress();String hostName1 = inetAddress1.getHostName();System.out.println("inetAddress1 = " + inetAddress1);System.out.println("ip1 = " + ip1);System.out.println("hostName1 = " + hostName1);}
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

报错是因为这个远程计算机的主机名是不存在的!

TCP:Socket和ServerSocket

通信的两端都要有Socket(也可以叫“套接字”),是两台机器间通信的端点。网络通信其实就是Socket间的通信。Socket可以分为:

  • 流套接字(stream socket):使用TCP提供可依赖的字节流服务
    • ServerSocket:此类实现TCP服务器套接字。服务器套接字等待请求通过网络传入。
    • Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
  • 数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
    • DatagramSocket:此类表示用来发送和接收UDP数据报包的套接字。

图示如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图示示例如下:

服务器端:

package top.sharehome.Demo;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 下面实现了一个服务器端*/
public class ICPServer {public static void main(String[] args) {ServerSocket serverSocket = null;InputStream inputStream = null;OutputStream outputStream = null;try {//使用serverSocket建立服务器端,并设置端口serverSocket = new ServerSocket(8888);//使用serverSocket类中的accept()方法获取接收端,即客户端的对象Socket accept = serverSocket.accept();//使用accept.getInputStream()方法创建输入流并从客户端获取内容inputStream = accept.getInputStream();byte[] arr = new byte[1024];int flag = inputStream.read(arr);System.out.println(new String(arr, 0, flag));System.out.println("accept = " + accept);//accept.getOutputStream()方法撞见一个输出流并向客户端输出内容outputStream = accept.getOutputStream();outputStream.write("thank".getBytes());} catch (IOException e) {e.printStackTrace();} finally {try {if (serverSocket != null) {serverSocket.close();}} catch (IOException e) {e.printStackTrace();}try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}try {if (outputStream != null) {outputStream.close();}} catch (IOException e) {e.printStackTrace();}}}
}

客户端:

package top.sharehome.Demo;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/*** 下面实现了一个客户端*/
public class ICPclient {public static void main(String[] args) {Socket socket = null;OutputStream outputStream = null;InputStream inputStream = null;try {//使用Socket建立客户端,并指定ip地址和端口socket = new Socket("127.0.0.1", 8888);//调用socket.getOutputStream()方法获取输出流并向服务器端输出内容outputStream = socket.getOutputStream();outputStream.write("Hello".getBytes());//调用socket.getInputStream()方法获取输入流并从服务器端输入内容inputStream = socket.getInputStream();byte[] arr = new byte[1024];int flag = inputStream.read(arr);System.out.println(new String(arr, 0, flag));System.out.println("socket = " + socket);} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null) {socket.close();}} catch (IOException e) {e.printStackTrace();}try {if (outputStream != null) {outputStream.close();}} catch (IOException e) {e.printStackTrace();}try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}}
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上传服务器死循环问题

在 I/O 流的学习中,我们结识到了通过循环来快速写入和读取的方法,但是这个循环放在客户端和服务器端之间就会出现很严重的问题,以 客户端通过基础流读取客户端文件数据然后向服务器写入数据,服务器端读取客户端数据后再通过基础流向服务器端文件里 为例:

//客户端相关操作代码:
byte[] bytes = new byte[1024];
int flag = 0;
while ((flag = fileInputStream.read(bytes)) != -1) {outputStream.write(bytes, 0, flag);
}
inputStream = socket.getInputStream();
flag = inputStream.read(bytes);
//服务器端相关操作代码:
byte[] bytes = new byte[1024];
int flag = 0;
while ((flag = inputStream.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, flag);
}

当客户端读取数据到客户端文件末尾处时会返回 -1,然后结束掉客户端的循环,但是由于 read() 方法的阻塞性,服务器端中的 read() 方法会一直等待着客户端继续写入数据,但是此时的客户端并不会再向服务器端传输数据,所以导致了服务器没办法完成该次相应,从而使客户端中的 read() 也进入了阻塞状态,进而进入一种双终端之间的死循环;

解决办法:

再写入完毕之后使用 Socket 类中的 shutdownOutput() 方法手动关闭写入通道,并且告诉对方自己已经写入完毕;

//客户端相关操作代码:
byte[] bytes = new byte[1024];
int flag = 0;
while ((flag = fileInputStream.read(bytes)) != -1) {outputStream.write(bytes, 0, flag);
}
socket.shutdownOutput();  //手动关闭写入通道
inputStream = socket.getInputStream();
flag = inputStream.read(bytes);
//服务器端相关操作代码:
byte[] bytes = new byte[1024];
int flag = 0;
while ((flag = inputStream.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, flag);
}

文件名重复问题

向服务器上传内容就类似于复制粘贴,如果粘贴时的文件名和粘贴路径中的文件有所重复,那么原来的文件就会被覆盖掉,这样的话向服务器上传文件始终只能是一个文件,所以我们要自定义一些文件名,最常见的就是 System.currentTimeMillis() 获取得到毫秒值再加上是 new Random().nextInt() 随机数;

示例如下:

//客户端相关代码:
fileInputStream = new FileInputStream("d:\\大学课程学习文档\\java\\Practice\\ImgClient\\1.jpg");  //由客户端读取客户端文件;
//服务器端相关代码:
fileOutputStream = new FileOutputStream("d:\\大学课程学习文档\\java\\Practice\\ImgServer\\" + System.currentTimeMillis() + new Random().nextInt(999999999) +".jpg");  //由服务器端接收客户端的数据并且将数据打包重命名为System.currentTimeMillis() + new Random().nextInt(999999999).jpg

图片上传案例

示例图片如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

客户端代码:

package top.sharehome.Demo;import java.io.*;
import java.net.Socket;public class ICPclient {public static void main(String[] args) {/*** 我们需要创建四个流* 1.连接服务器* 2.字节流将图片引入* 3.链接对象的字节输出流,将图片写入服务器* 4.读取服务器返回的上传成功的消息*/FileInputStream fileInputStream = null;OutputStream outputStream = null;Socket socket = null;InputStream inputStream = null;try {socket = new Socket("127.0.0.1", 8888);fileInputStream = new FileInputStream("d:\\大学课程学习文档\\java\\Practice\\ImgClient\\1.jpg");outputStream = socket.getOutputStream();byte[] bytes = new byte[1024];int flag = 0;while ((flag = fileInputStream.read(bytes)) != -1) {outputStream.write(bytes, 0, flag);}socket.shutdownOutput();inputStream = socket.getInputStream();flag = inputStream.read(bytes);System.out.println("socket = " + socket);System.out.println(new String(bytes, 0, flag));} catch (IOException e) {e.printStackTrace();} finally {try {if (fileInputStream != null) {fileInputStream.close();}} catch (IOException e) {e.printStackTrace();}try {if (socket != null) {socket.close();}} catch (IOException e) {e.printStackTrace();}}}
}

服务器端代码:

package top.sharehome.Demo;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;public class ICPServer {public static void main(String[] args) {/*** 我们需要建立三个流* 1.和客户端建立连接* 2.接收客户端传来的数据* 3.返回上传成功的信息*/ServerSocket serverSocket = null;FileOutputStream fileOutputStream = null;InputStream inputStream = null;OutputStream outputStream = null;Socket client = null;try {serverSocket = new ServerSocket(8888);client = serverSocket.accept();fileOutputStream = new FileOutputStream("d:\\大学课程学习文档\\java\\Practice\\ImgServer\\" + System.currentTimeMillis() + new Random().nextInt(999999999) +".jpg");inputStream = client.getInputStream();byte[] bytes = new byte[1024];int flag = 0;while ((flag = inputStream.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, flag);}System.out.println("client = " + client);outputStream = client.getOutputStream();outputStream.write("上传图片成功!".getBytes());} catch (IOException e) {e.printStackTrace();} finally {try {if (serverSocket != null) {serverSocket.close();}} catch (IOException e) {e.printStackTrace();}try {if (fileOutputStream != null) {fileOutputStream.close();}} catch (IOException e) {e.printStackTrace();}try {if (client != null) {client.close();}} catch (IOException e) {e.printStackTrace();}}}
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

UDP:DatagramSocket

基于UDP协议的网络编程仍然需要在通信实例的两端各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接收数据报的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收的数据报;

DatagramSocket 类的常用方法:

  • public DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被绑定到通配符地址,IP 地址由内核来选择;
  • public DatagramSocket(int port,InetAddress laddr)创建数据报套接字,将其绑定到指定的本地地址。本地端口必须在 0 到 65535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地址,IP 地址由内核选择;
  • public void close()关闭此数据报套接字;
  • public void send(DatagramPacket p)从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号;
  • public void receive(DatagramPacket p)从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。 此方法在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短;

DatagramPacket类的常用方法:

  • public DatagramPacket(byte[] buf,int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。 length 参数必须小于等于 buf.length;
  • public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。length 参数必须小于等于 buf.length;
  • public int getLength()返回将要发送或接收到的数据的长度;

示例代码

发送端:

package top.sharehome.Demo;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;public class Send {public static void main(String[] args)throws Exception {
//		1、建立发送端的DatagramSocketDatagramSocket ds = new DatagramSocket();//要发送的数据ArrayList<String> all = new ArrayList<String>();all.add("hello java");all.add("hello C");all.add("hello php");all.add("hello python");//接收方的IP地址InetAddress ip = InetAddress.getByName("127.0.0.1");//接收方的监听端口号int port = 9999;//发送多个数据报for (int i = 0; i < all.size(); i++) {
//			2、建立数据包DatagramPacketbyte[] data = all.get(i).getBytes();DatagramPacket dp = new DatagramPacket(data, data.length, ip, port);
//			3、调用Socket的发送方法ds.send(dp);}//		4、关闭Socketds.close();}
}

接收端:

package top.sharehome.Demo;import java.net.DatagramPacket;
import java.net.DatagramSocket;public class Receive {public static void main(String[] args) throws Exception {
//		1、建立接收端的DatagramSocket,需要指定本端的监听端口号DatagramSocket ds = new DatagramSocket(9999);//一直监听数据while(true){//		2、建立数据包DatagramPacketbyte[] buffer = new byte[1024*64];DatagramPacket dp = new DatagramPacket(buffer , buffer.length);//		3、调用Socket的接收方法ds.receive(dp);//4、拆封数据String str = new String(buffer,0,dp.getLength());System.out.println(str);}}
}

下一章:由浅到深认识Java语言(40):枚举

相关文章:

由浅到深认识Java语言(39):网络编程

该文章Github地址&#xff1a;https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.c…...

PCL 彩色点云RGB转灰度并显示

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、原理概述 不同要素之间的灰度差异较为明显。点云灰度值与RGB属性的关系为:...

RHEL9部署Docker环境

华子目录 Docker引擎架构docker引擎架构示意图执行过程示例 RHEL9上安装Docker1.系统要求2.安装yum-utils工具包3.yum安装docker-ce4.配置docker镜像加速docker拉取镜像的过程配置阿里云镜像仓库重新加载守护进程重启Docker服务 5.拉取并运行hello-world镜像6.测试是否安装成功…...

Vue3.0云里雾里

目录:一篇通识Vue3.0 1.OptionsAPI(选项式)和CompositionAPI(组合式) 2.setup setup语法糖 ref响应式数据 reactive只能定义对象类型的响应式数据(用情专一) toRefs解构 计算属性computed watch侦听 WatchEffect 标签的Ref属性 组件上的ref就是获取组件实例…...

idea类已经存在却报错

一句话导读 在idea中导入新的项目&#xff0c;很多类都飘红报错&#xff0c;mvn compile可以通过&#xff0c;可能是因为idea缓存问题导致。 由于这个项目是由老项目复制过来后&#xff0c;再继续开发新的功能&#xff0c;很多同事导入后&#xff0c;都爆出新的类找不到。而编译…...

MySQL---视图

目录 一、介绍 二、语法 三、视图的更新 四、视图作用 一、介绍 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 通俗的讲&#…...

策略路由-IP-Link-路由协议简介

策略路由 策略路由和路由策略的不同 1.策略路由的操作对象是数据包&#xff0c;在路由表已经产生的情况下&#xff0c;不按照路由表进行转发&#xff0c;而是根据需要&#xff0c;依照某种策略改变数据包的转发路径 2.路由策略的操作对象是路由信息。路由策略的主要实现了路…...

数位五五(Java)

数位五五 题目描述 求出[a,b]区间内有多少个数数位之和为 55 的倍数。 输入格式 输入一行包含两个整数a &#xff0c;b。 输出格式 输出一个整数。 样例输入输出 样例输入 10 20样例输出 2数据范围 对于 100% 的数据&#xff0c;保证 1≤a≤b≤1000000。 样例解释 …...

蓝桥杯G431RBT6——定时器中使用led冲突以及led与lcd冲突等一系列问题

本文是解决 同时在 定时器中点灯 与 LCD屏幕显示 冲突异常的问题 我们大家都知道&#xff0c;G431RBT6开发板上led与lcd是冲突的&#xff0c;所以在lcd.c文件中的这三个函数中 void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) void LCD_WriteRAM_Prepare(void) void LCD_Wr…...

物联网(IoT)常用的通信协议

物联网&#xff08;IoT&#xff09;的通信协议是物联网设备之间交换数据的规则和标准。这些协议对于确保设备能够有效、安全地通信至关重要。下面是物联网通信协议的概述&#xff1a; 1. MQTT&#xff08;消息队列遥测传输&#xff09; 概述&#xff1a;MQTT是一种轻量级的发…...

关于C/C++,Linux/MacOS/Windows 平台虚拟内存分配

在 Windows 平台上面建议通过 VirtualAlloca、VirtualAllocaEx 核心库函数来分配虚拟内存&#xff0c;而不是通过 MMF&#xff08;Memory Mapping File / 内存映射文件&#xff09;技术来载入虚拟内存。 这是因为&#xff0c;在 Windows 平台上面&#xff0c;通过MMF技术分配的…...

如何在服务器上传/下载文件

从服务器下载文件到本地 打开xshell&#xff0c;输入&#xff1a;ssh root159.xxx.xxx.xx 然后需要输入密码 cd到目录文件夹下 cd /enmotech apt install zip zip -r uploads.zip uploads apt install lrzsz sz uploads.zip 从本地上传文件到服务器 如果文件是放在E盘…...

C++ 之多态虚函数原理及应用

文章目录 多态基本概念和原理虚函数的基本原理和概念虚析构和纯虚析构多重继承中的虚函数小结 多态基本概念和原理 多态的基本概念 **多态是C面向对象三大特性之一** 多态的定义 多态是一种面向对象编程概念&#xff0c;指同一个行为&#xff08;方法&#xff09;在不同的对象上…...

亮数据——让你的IP走出去,让价值返回来

亮数据——让你的IP走出去&#xff0c;让价值返回来 前言跨境电商最最最大的痛点——让IP走出去超级代理服务器加速网络免费的代理管理软件亮数据解决痛点亮数据优势介绍亮数据浏览器的使用示例总结 前言 当前社会信息的价值是不可想象的&#xff0c;今天在亮数据中看到了个【…...

spring boot-引入Redis并封装redistemplate操作工具类

文章目录 一、关于spring-redis二、springboot引入Redis及其使用案例三、封装redistemplate操作工具类 一、关于spring-redis spring-data-redis针对jedis提供了如下功能&#xff1a; 连接池自动管理&#xff0c;提供了一个高度封装的“RedisTemplate”类 针对jedis客户端中大…...

android 11 SystemUI 状态栏打开之后的界面层级关系说明之一

比如WiFi 图标的父layout为&#xff1a; Class Name: ButtonRelativeLayout Class Name: QSTileView Class Name: TilePage Class Name: PagedTileLayout Class Name: QSPanel Class Name: NonInterceptingScrollView Class Name: QSContainerImpl Class Name: FrameLayout Cl…...

C#___锁(lock)

lock是一种语言级别的关键字&#xff0c;用于实现线程同步和互斥。它提供了一种简单的方式来确保多个线程不会同时访问共享资源&#xff0c;从而避免竞争条件和数据不一致的问题。 作用&#xff1a; 1、避免并行运算中&#xff0c;共享数据的的读写安全问题&#xff1b; 2、并…...

JAVA的sort用法详解(二维数组排序,List<>排序,lambada表达式,自定义类型排序)

目录 前言&#xff1a; 一维数组降序&#xff1a; 方法1.Comparator接口&#xff1a; 代码实现&#xff1a; 方法2.Collections.reverseOrder()&#xff1a; 代码实现&#xff1a; 二维数组排序&#xff1a; 代码如下&#xff1a; List<>排序&#xff1a; 代码…...

数据分析能力模型分析与展示

具体内容&#xff1a; 专业素质 专业素质-01 数据处理 能力定义•能通过各种数据处理工具及数据处理方法&#xff0c;对内外部海量数据进行清洗和运用&#xff0c;提供统一数据标准&#xff0c;为业务分析做好数据支持工作。 L1•掌握一…...

BUG未解之谜01-指针引用之谜

在leetcode里面刷题出现的问题&#xff0c;当我在sortedArrayToBST里面给root赋予初始值NULL之后&#xff0c;问题得到解决&#xff01; 理论上root是未初始化的变量&#xff0c;然后我进入insert函数之后&#xff0c;root引用的内容也是未知值&#xff0c;因此无法给原来的二叉…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

算法笔记2

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

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...