猿创征文|UDP/TCP网络编程

news/2024/4/30 13:56:08/文章来源:https://blog.csdn.net/qq_60856948/article/details/126648824

在这里插入图片描述
请添加图片描述

⭐️前言⭐️

🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【JavaSE】、【备战蓝桥】、【JavaEE初阶】、【MySQL】、【数据结构】
🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)、GitHub


请添加图片描述

📍内容导读📍

  • UDP/TCP网络编程
    • 🍅1.网络编程中的基本概念
      • 1.1 请求和响应
      • 1.2 客户端--服务器通信流程
    • 🍅2.Socket套接字
    • 🍅3.UDP网络编程
      • 3.1 关键API
      • 3.2 回显程序
      • 3.3 翻译程序
    • 🍅4.TCP网络编程
      • 4.1 关键API
      • 4.2 回显程序
      • 4.3 回显程序(多线程升级版)
      • 4.4 回显程序(线程池升级版)
      • 4.5 翻译程序

请添加图片描述

UDP/TCP网络编程

🍅1.网络编程中的基本概念

1.1 请求和响应

一般来说,如果我们想要获取一个网络资源,就需要涉及到两次网络传输:

  • 第一次:请求数据的发送
  • 第二次:响应数据的发送

就好比我们在快餐店点一份盖浇饭:
先发起请求:老板来份盖浇饭,再有快餐店提供的对应响应:提供一份炒饭
在这里插入图片描述

1.2 客户端–服务器通信流程

服务器:在网络传输数据场景下负责提供服务的一方
客户端:获取服务的一端
在这里插入图片描述

🍅2.Socket套接字

操作系统把与网络编程一些相关的操作封装了起来,提供了一组API供程序猿来调用,这组API就是Socket API
这组API的主要功能就是为了操作网卡这个硬件设备,来完成数据的传输

操作系统对于网卡进行了抽象,在进程想去操作网卡的时候,就会打开一个“scoket”文件,通过读写这个文件,就能读写网卡了。(一切皆文件的思想)

系统所提供的Socket API共有两种风格:
一种是基于UDP的(数据包),另一种是基于TCP的(字节流)
这两种API有各自以下特点:
在这里插入图片描述

对上述特点的解释:

  1. 有连接就像是打电话,无连接就像是发微信
  2. 可靠传输:发送方能够知道对方是否收到了消息
    不可靠传输:发送方不能知道对方是否收到了消息
  3. 面向数据包:以一个一个的数据包为基本单位进行数据传输(只能整个发送,半个接收不到,也发不出去)
    面向字节流:可以自己定义发送和接收的字节总数及方式,比较灵活
  4. 全双工:双向通信-》A和B可以同时向对方发送接收数据
    半双工:单向通信-》要么A给B发,要么B给A发,不能同时发

🍅3.UDP网络编程

3.1 关键API

DatagramSocket: 对socket文件进行了封装

构造方法:
1)无参:客户端使用(此时端口号由系统分配)
在这里插入图片描述
2)有参:服务器使用(此时由用户指定端口号)
在这里插入图片描述
主要方法:
在这里插入图片描述

DatagramPacket: 对UDP数据包进行封装

构造方法:
1)传入空的缓冲区,构造一个空的packet(在receive方法时使用)
在这里插入图片描述

2)传入一个有数据的缓冲区,指定目标的IP和端口
在这里插入图片描述

3)传入一个有数据的缓冲区,指定目标的SocketAddress(内含目标的IP和端口)
在这里插入图片描述

3.2 回显程序

该程序只是简单实现了——客户端发送什么,服务器就回应什么的功能。

服务器
设计步骤:
1.读取请求
2.根据请求来计算响应
3.把响应写回客户端
4.加上日志打印

public class UdpEchoServer {private DatagramSocket socket = null;/*** 服务器在启动的时候需要绑定一个端口号* 在收到数据的时候,就会根据这个端口号来决定把数据交给哪个进程** @param port 端口号(范围为0~65535)* @throws SocketException*/public UdpEchoServer(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);/*参数DatagramPacket是一个输出型参数,socket中读到的数据会设置到这个参数的对象中在构造的时候,需要指定一个缓冲区(就是一段内存空间,通常使用byte[])*/socket.receive(requestPacket);/*当前服务器不知道客户端什么时候发来请求,receive方法会阻塞等待如果有请求过来了,此时receive就会返回*/String request = new String(requestPacket.getData(), 0,requestPacket.getLength());//把requestPacket对象里面的内容取出来,作为一个字符串//2.根据请求来计算响应String response = process(request);//3.把响应写回客户端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,requestPacket.getSocketAddress());/*此处给DatagramPacket中设置的长度,必须是“字节的个数”,而且在构造的时候,还需要指定这个包发给谁(其实发送给的目标就是发请求的那一方) */socket.send(responsePacket);//4.加上日志打印String log = String.format("[%s:%d] req: %s ;resp: %s",requestPacket.getAddress().toString(), requestPacket.getPort(), request, response);System.out.println(log);}}/*** 根据请求来计算响应的方法(此处仅为一个回显服务器,只把客户端发来的请求返回即可)** @param request* @return*/private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server=new UdpEchoServer(9090);server.start();}
}

客户端
设计步骤:
1.从标准输入流输入数据
2.把字符串构造成UDP请求,并发送数据
3.尝试从服务器读取响应
4.显示这个结果

public class UdpEchoClient {private DatagramSocket socket=null;private String serverIP;private int serverPort;/**** @param serverIP  服务器的IP* @param serverPort 服务器的端口* @throws SocketException*/public UdpEchoClient(String serverIP,int serverPort) throws SocketException {this.serverIP=serverIP;this.serverPort=serverPort;this.socket = new DatagramSocket();//此处实例化Socket不用指定端口号,操作系统会随机分配空闲端口}public void start() throws IOException {Scanner scanner=new Scanner(System.in);while(true) {System.out.print("->");//1.从标准输入流输入数据String request=scanner.nextLine();if(request.equals("exit")) {System.out.println("exit!");return;}//2.把字符串构造成一个UDP请求,并发送数据DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIP),serverPort);socket.send(requestPacket);//3.尝试从服务器读取响应DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//4.显示这个结果String response=new String(responsePacket.getData(),0, responsePacket.getLength());String log=String.format("req: %s ;resp: %s",request,response);System.out.println(log);}}public static void main(String[] args) throws IOException {UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);client.start();}
}

3.3 翻译程序

与2.2的回显程序框架相同,只是在process方法中加入了逻辑(也就是根据请求来计算响应的模块)。
该程序利用哈希表一一对应的结构,完成了一个简单的翻译功能。

服务器
设计步骤:
1.读取请求并解析
2.根据请求计算响应
3.把响应写回到客户端
4.日志打印

public class UdpDictServer {private DatagramSocket socket=null;private HashMap<String,String> dict=new HashMap<>();//词典  哈希表 一一对应public UdpDictServer(int port) throws SocketException {this.socket = new DatagramSocket(port);//初始化词典内容dict.put("hello","你好");dict.put("cat","小猫");dict.put("dog","小狗");}public void start() throws IOException {System.out.println("服务器启动!");while(true) {//1.读取请求并解析DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);String request=new String(requestPacket.getData(),0, requestPacket.getLength());//2.根据请求计算响应String response=process(request);//3.把响应写回到客户端DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//4.日志打印String log=String.format("[%s:%d] req: %s;resp: %s",requestPacket.getAddress(),requestPacket.getPort(),request,response);System.out.println(log);}}private String process(String request) {return dict.getOrDefault(request,"[单词在词典中不存在!]");}public static void main(String[] args) throws IOException {UdpDictServer server=new UdpDictServer(9090);server.start();}
}

客户端
设计步骤:
1.读取输入的数据
2.构造请求并发送给服务器
3.从服务器获取响应
4.把数据显示给用户

public class UdpDictClient {private DatagramSocket socket=null;private String serverIP;private int serverPort;public UdpDictClient(String serverIP,int serverPort) throws SocketException {this.serverIP=serverIP;this.serverPort=serverPort;this.socket=new DatagramSocket();}public void start() throws IOException {Scanner scanner=new Scanner(System.in);while (true) {//1.读取输入的数据System.out.print("->");String request=scanner.next();if(request.equals("exit")) {System.out.println("goodbye!");return;}//2.构造请求并发送给服务器DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIP),serverPort);socket.send(requestPacket);//3.从服务器获取响应DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response=new String(responsePacket.getData(),0, responsePacket.getLength());//4.把数据显示给用户String log=String.format("req: %s;resp: %s",request,response);System.out.println(log);}}public static void main(String[] args) throws IOException {UdpDictClient client=new UdpDictClient("127.0.0.1",9090);client.start();}
}

🍅4.TCP网络编程

4.1 关键API

ServerSocket: 用于服务器
Socket:服务器和客户端都需要使用

服务器流程:

  1. 创建ServerSocket关联上一个端口号。(该socket称为listenSocket,用于建立连接
  2. 调用ServerSocketaccept方法,accept方法返回一个Socket实例,称为clientSocket(用于客户端和服务器的进一步交互
  3. 使用clientSocket的getInputStream和getOutputStream得到字节流对象,就可以进行读取和写入操作了。
  4. 当客户端断开连接后,服务器应及时关闭clientSocket,防止出现文件资源泄露的情况

客户端流程:

  1. 创建一个Socket对象,创建时同时指定服务器的IP和端口号(该操作会让客户端和服务器建立TCP连接,也就是“三次握手”的过程,具体后续讲解)
  2. 客户端可以通过Socket对象的getInputStream和getOutputStream来和服务器进行通信

4.2 回显程序

服务器设计步骤
1.读取请求并解析
2.根据请求计算响应
3.把响应写回客户端

public class TcpEchoServer {private ServerSocket listenSocket=null;public TcpEchoServer(int port) throws IOException {this.listenSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while(true) {/*UDP的服务器进入主循环,就直接尝试receive读取请求了,但是TCP是有连接的,先需要做的是建立好连接,当服务器运行的时候,不确定当前是否有客户端来建立连接如果客户端没有建立连接,accept就会阻塞等待如果客户端建立连接了,此时accept就会返回一个Socket对象,进一步的服务器与客户端间的交互就交给clientSocket来完成了*/Socket clientSocket=listenSocket.accept();processConnection(clientSocket);}}/*** 处理一个连接。在这个连接中可能会涉及到客户端和服务器的多次交互* @param clientSocket*/private void processConnection(Socket clientSocket) throws IOException {String log=String.format("[%s:%d] 客户端上线!",clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);try(InputStream inputStream= clientSocket.getInputStream();OutputStream outputStream= clientSocket.getOutputStream()) {while (true) {//1.读取请求并解析Scanner scanner=new Scanner(inputStream);/*进入方法后代码在Scanner.hasNext阻塞,等待客户端发送请求;在读取到客户端请求后会结束阻塞,读取到数据并处理返回响应,循环转一圈后又会在hasNext阻塞。只有当客户端退出的时候才会结束循环。*/if(!scanner.hasNext()) {log=String.format("[%s:%d] 客户端下线!",clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);//打印下线日志break;}String request=scanner.next();//2.根据请求计算响应String response=process(request);//3.把响应写回客户端PrintWriter writer=new PrintWriter(outputStream);writer.println(response);writer.flush();log=String.format("[%s:%d] req: %s;resp: %s",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);System.out.println(log);}} catch (IOException e) {e.printStackTrace();} finally {/*当前的clientSocket的生命周期不是跟随整个程序,而是和连接相关因此就需要每个连接结束时,都要进行关闭否则随着连接的增多,这个socket文件就可能出现资源泄露的情况*/clientSocket.close();}}/*** 回显服务器:客户端发什么就返回什么* @param request* @return*/public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server=new TcpEchoServer(9090);server.start();}
}

客户端设计步骤
1.从键盘上读取用户输入的内容
2.把读取的内容构造成请求,发送给服务器
3.从服务器读取响应并解析
4.把结果显示到界面上

public class TcpEchoClient {private String serverIP;private int serverPort;private Socket socket=null;public TcpEchoClient(String serverIP,int serverPort) throws IOException {this.serverIP = serverIP;this.serverPort=serverPort;//TCP网络编程中,让socket创建的同时,就和服务器尝试建立连接this.socket=new Socket(serverIP,serverPort);}public void start() {Scanner scanner=new Scanner(System.in);try (InputStream inputStream= socket.getInputStream();OutputStream outputStream= socket.getOutputStream()){while(true) {//1.从键盘上读取用户输入的内容System.out.print("->");String request=scanner.next();if(request.equals("exit")) {break;}//2.把读取的内容构造成请求,发送给服务器PrintWriter printWriter=new PrintWriter(outputStream);printWriter.println(request);printWriter.flush();//3.从服务器读取响应并解析Scanner respScanner=new Scanner(inputStream);String response=respScanner.next();//4.把结果显示到界面上String log=String.format("req: %s;resp: %s",request,response);System.out.println(log);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client=new TcpEchoClient("127.0.0.1",9090);client.start();}
}

4.3 回显程序(多线程升级版)

在实际开发中,一个服务器应该对应很多个客户端,但如果按照4.2的代码写法,一个服务器只能服务于一个客户端。在idea中启动第二个客户端时,服务器并不会提示客户端2上线。

我们来看服务器的操作流程:
最开始时,没有客户端建立连接,此时服务器阻塞在accept方法上

在这里插入图片描述

当有客户端连上后,accept返回,得到clientScoket,并进入processConnection方法中;进入方法后代码在Scanner.hasNext阻塞,等待客户端发送请求;在读取到客户端请求后会结束阻塞,读取到数据并处理返回响应,循环转一圈后又会在hasNext阻塞。只有当客户端退出的时候才会结束循环。

在这里插入图片描述

为了解决这个问题,我们可以主线程中循环调用accept,每次获取到一个连接,就创建一个线程来给客户端提供服务
代码如下:

public class TcpThreadEchoServer {private ServerSocket listenSocket=null;public TcpThreadEchoServer(int port) throws IOException {this.listenSocket =new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while(true) {//主线程中循环调用accept,就能保证在一次调用完成后,立刻进行再次调用Socket clientSocket=listenSocket.accept();//每次获取到一个连接,就创建一个线程来给客户端提供服务Thread t=new Thread(()->{try {processConnection(clientSocket);} catch (IOException e) {e.printStackTrace();}});t.start();}}private void processConnection(Socket clientSocket) throws IOException {String log=String.format("[%s:%d] 客户端上线!",clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);try(InputStream inputStream= clientSocket.getInputStream();OutputStream outputStream= clientSocket.getOutputStream()) {while(true) {//1.读取并请求解析Scanner scanner=new Scanner(inputStream);if(!scanner.hasNext()) {log=String.format("[%s:%d] 客户端下线!",clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);break;}String request= scanner.next();//2.根据请求计算响应String response=process(request);//3.把响应写回客户端PrintWriter printWriter=new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();log=String.format("[%s:%d] req: %s;resp: %s",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);System.out.println(log);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpThreadEchoServer server=new TcpThreadEchoServer(9090);server.start();}
}

4.4 回显程序(线程池升级版)

在4.3中我们通过多线程的方法解决了一个服务器服务于多个客户端的问题,但是如果有很多的客户端连接又退出,就会导致当前的服务器里频繁创建销毁线程,有很大的成本,为了改进这个问题,我们可以引进线程池,这样就既能处理多个客户端,也不需要频繁创建销毁线程了

代码如下:

public class TcpThreadPoolEchoServer {private ServerSocket listenSocket=null;public TcpThreadPoolEchoServer(int port) throws IOException {this.listenSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");ExecutorService executorService= Executors.newCachedThreadPool();while (true) {Socket clientSocket=listenSocket.accept();//使用线程池来处理当前的processConnectionexecutorService.submit(()->{try {processConnection(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}public void processConnection(Socket clientSocket) throws IOException {String log = String.format("[%s:%d] 客户端上线!", clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {while (true) {// 1. 读取请求并解析Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()) {log = String.format("[%s:%d] 客户端下线!", clientSocket.getInetAddress().toString(),clientSocket.getPort());System.out.println(log);break;}String request = scanner.next();// 2. 根据请求计算响应String response = process(request);// 3. 把响应写回到客户端PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();log = String.format("[%s:%d] req: %s; resp: %s", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);System.out.println(log);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpThreadPoolEchoServer server=new TcpThreadPoolEchoServer(9090);server.start();}
}

4.5 翻译程序

有了上边的优化,我们再来给服务器添加功能,完成翻译,由UDP翻译程序我们可以知道,其实主要更改的逻辑就是process方法中根据请求计算响应,为了代码复用,我们可以直接继承4.4,成为其子类,再只重写process方法即可。

代码如下:

public class TcpDictServer extends TcpThreadPoolEchoServer{private HashMap<String,String> dict=new HashMap<>();public TcpDictServer(int port) throws IOException {super(port);//初始化哈希表dict.put("hello","你好");dict.put("cat","小猫");dict.put("dog","小狗");}//start方法不需要变动//processConnection方法也不需要改变//仅把回显功能改为翻译功能即可 (仅修改process)@Overridepublic String process(String request) {return dict.getOrDefault(request,"[要查的词不存在]");}public static void main(String[] args) throws IOException {TcpDictServer server=new TcpDictServer(9090);server.start();}
}

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis主从库网络断连问题——repl_backlog_buffer

主从库间网络断了怎么办&#xff1f; 在 Redis 2.8 之前&#xff0c;如果主从库在命令传播时出现了网络闪断&#xff0c;那么&#xff0c;从库就会和主库重新进行一次全量复制&#xff0c;开销非常大。 从 Redis 2.8 开始&#xff0c;网络断了之后&#xff0c;主从库会采用增量…

hashmap底层原理解析

底层数据结构&#xff0c;1.7与1.8有何不同? 为何要用红黑树&#xff0c;为何一上来不树化&#xff1f;树化阈值为何是8&#xff1f;何时会树化&#xff1f;何时会退化为链表? 链表比较短的时候&#xff0c;查询性能并没有那么低&#xff0c;不用费劲把它转成红黑树&#xff…

项目经理如何做好项目管理中的风险管理

项目中始终有些看不见的风险&#xff0c;这些风险可以成为威胁&#xff0c;也有可能会影响到项目的计划发生重大的变化。 一、项目目标不明确 确定项目目标是项目启动阶段重要的工作之一&#xff0c;要想项目在实施阶段少走弯路&#xff0c;在项目开工前&#xff0c;必须清晰…

信息系统项目管理师Part16-物联网

物联网 1.物联网的两项关键技术 传感器技术、嵌入式技术 2.传感器技术和嵌入式技术 RFID射频识别&#xff1a;可通过无线电信号识别特定目标并读写相关数据&#xff0c;而无需识别系统与特定目标之间建立机械或光学接触。 嵌入式技术&#xff1a;是综合了计算机硬件、传感器技…

猿创征文|OLAP之apache pinot初体验

目录 一、背景 二、介绍 三、特征 四、价值 五、参考组件 组件清单介绍&#xff1a; 1.Controller 2.Server 3.Broker 4.Minion (optional) 六、数据采集 批量数据流程 实时数据流程 查询处理流程 一、背景 最近在熟悉公司内部的埋点采集&#xff0c;发现数据架构…

NK-RTU980 CAP

BSP包中有两个CAP相关的例程&#xff0c;两个例程的区别为获取的图像数据的存储格式不同&#xff0c;planar例程是先存储所有像素点的Y&#xff0c;再存U&#xff0c;再存V。packed例程是每个像素的YVU连续存储。 一、硬件电路 处理器为NUC980DR61Y&#xff0c;封装为64pin&a…

python--转换wrf输出的风场数据为网页可视化的json格式

前言&#xff1a; 一般网页可视化风场中的数据都是json格式&#xff0c;而如果我们希望将wrf模式模拟输出的风场数据在网页中进行展示&#xff0c;这就需要先将wrfoutput数据转换为网页可以识别的json格式。 这里主要需要用到json库&#xff0c;主要的实现方式就是将读取的风场…

微信网课答案公众号题库接口使用

微信网课答案公众号题库接口使用 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&…

亚马逊审核 美国站安全带ASTMF1772安全绳攀岩绳EN892认证流程

1 登山锁扣定义 登山用锁扣是一种带弹簧门的金属环状物&#xff0c;用于在攀岩和登山时快速可逆地连接各部件&#xff0c;是安全系统关键的一部分。 登山用锁扣可用于将绳索固定到设备上&#xff0c;或者将两件或多件设备连接在一起。它们通常由铝或钢制成。这种锁扣具有不同…

ps2021神经ai滤镜无法使用,ps2021没法用神经元滤镜

如何解决ps2021 新版 AI神经滤镜不能用? 网上买正版&#xff0c;更新下就好了&#xff0c;盗版的都会有各种这样的问题。ps2021神经AI滤镜是需简要上传云端&#xff0c;由Adobe官方服务器人工智能运算的。 Ps2021版本新增了Ai神经元滤镜&#xff0c;它不是与软件一起安装的&…

谣言粉碎机?Python验证股市操盘口诀

更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流。 经常炒股的朋友,应该都听说过这段操盘口诀: 早上大跌要买,早上大涨要卖 下午大涨不追,下午大跌次日买 早上大跌不割,不涨不跌睡觉 我们随手百度,也能发现各大主流论坛,充斥着该口…

Spring入门——Eclipse实现HelloWorld程序

前言 疫情影响又延期开学&#xff0c;只能在家上上网课划划水&#xff0c;刚做完spring入门的一个小作业&#xff0c;来做个总结分享&#xff0c;我也是个刚入门的小白&#xff0c;还望大佬们指点。 步入主题 环境 eclipse/spring-tool-suite-3 jdk1.8.0_221 另外&#xff0…

Linux :mysql数据库自动备份

Linux &#xff1a;mysql数据库自动备份前言使用shell脚本进行数据库的定时备份确定备份数据库备份shell脚本定时shell脚本前言 当项目发布到服务器上后&#xff0c;接下来考虑到就是如何做好数据库的数据备份。为的就是防止服务器突然异常崩溃&#xff0c;而导致的数据丢失问…

使用上下游思维实现系统解耦

在软件开发领域&#xff0c;解耦这个词相信大家都不陌生。在面向对象的语境下&#xff0c;我们会应用SOLID原则来构建高内聚低耦合的应用&#xff0c;实现模块间的解耦&#xff1b;在复杂业务系统分析和建模时&#xff0c;会通过DDD的战略和战术设计帮助划分领域并实现分布式系…

Java毕业设计-校园活动赞助与宣传管理系统

&#x1f525;作者主页&#xff1a;疯狂行者&#x1f525; &#x1f496;✌java领域优质创作者,专注于Java技术领域技术交流✌&#x1f496; &#x1f496;文末获取源码&#x1f496; 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1…

(分布式缓存)Redis持久化

一、RDB持久化 首先需要在Linux系统中安装一个Redis&#xff0c;如果尚未安装的同学&#xff0c;可以参考下面链接教程安装先&#xff1a; (73条消息) 单机安装Redis_其然乐衣的博客-CSDN博客 修改配置文件 创建一个数据 因为设置了只要5秒内有一次修改就会触发一次备份数据&am…

最全 Burp Suite 最新付费稳定版安装教程

介绍 Burp Suite是web应用程序渗透测试集成平台。从应用程序攻击表面的最初映射和分析,到寻找和利用安全漏洞等过程,所有工具为支持整体测试程序而无缝地在一起工作。 平台中所有工具共享同一robust框架,以便统一处理HTTP请求、持久性、认证、上游代理、日志记录、报警和可扩…

《QDebug 2022年8月》

一、Qt Widgets 问题交流 1.QWidget鼠标事件穿透 对于一些透明或者半透明的QWidget&#xff0c;可能需要点击其下方的按钮或其他组件&#xff0c;但是QWidget本身是会接收这些鼠标事件的&#xff0c;需要一些额外的处理。下面是百度到的一些方法&#xff1a; 方式A.设置setA…

Nacos下载和安装-windows

Nacos官网&#xff1a;https://nacos.io/zh-cn/ Nacos官方文档&#xff1a;https://nacos.io/zh-cn/docs/quick-start.html 一、下载 进入nacos官网&#xff0c;选择相应版本下载 github上nacos的zip资源&#xff0c;下载速度奇慢问题。 百度网盘&#xff1a;https://pan.b…

云原生游戏第 2 讲:OpenKruiseGame 设计理念详解

后疫情时代&#xff0c;游戏行业步入高质量发展期&#xff0c;游戏云原生化势在必行。不久前&#xff0c;针对游戏行业云原生落地的难点、游戏玩家服容器化的困境等问题&#xff0c;阿里云容器服务团队通过直播课程《云原生游戏第1讲&#xff1a;游戏玩家服容器化的困境与解法》…