《Java-SE-第三十一章》之网络编程

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


文章目录

  • 网络编程
    • 为什么需要网编程?
    • 什么是网络编程
    • 网络编程中的基本概念
      • 发送端和接收端
      • 请求和响应
      • 客户端和服务端
      • 常见的客户端服务端模型
    • Socket套接字
      • 概念
      • 套接字分类
        • Java数据报套接字通信模型
        • Java流套接字通信模型
      • UDP数据报套接字编程
          • UDP客户端服务器回显服务程序
          • UDP客户端服务器简单翻译服务程序
      • TCP流套接字编程
        • TCP客户端服务器回显服务程序
      • TCP中的长短连接
        • 一发一收(短连接)

网络编程

为什么需要网编程?

&ebsp;&ebsp;当我们使用浏览器进行搜索时,浏览器会根据关键字搜索出视频,图片文本等资源,这些资源都属于网络资源。网络资源相比于本地资源来说更加的丰富多彩。而这些网络资源都需要通过网络编程来进行数据传输。

什么是网络编程

&ebsp;&ebsp;网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络数据传输。但是,同一台主机上的不同进程,如果是基于网络来进行通信,也属于网络编程。

在这里插入图片描述

网络编程中的基本概念

发送端和接收端

在一次网络数据传输时:

发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。

接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。

收发端:发送端和接收端两端,也简称为收发端。

注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

在这里插入图片描述

请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输:

第一次:请求数据的发送,告诉服务端我要获取xx资源。

第二次:响应数据的发送,服务端返回给客户端xx资源。

举个栗子,这就好比,在外面吃饭,你跟老板说来一份青椒炒肉,自然就会给你提供一份青椒炒肉。
在这里插入图片描述

客户端和服务端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务,就像我们平时用的B站app上面的视频,图片等资源,都是通过网络从服务器上得到数据,然后通过网络传输到app上。

客户端获取服务的一方进程,称为客户端。简单来说就是各种软件。

对于服务来说,一般是提供:

  • 客户端获取服务资源

在这里插入图片描述

  • 客户端保存资源在服务端
    在这里插入图片描述

举个栗子, 银行提供了存款服务,用户(客户端)把钱(资源)存在银行(服务端)。同时银行提供了取款服务,用户可以去银行取钱(获得服务端资源)。

常见的客户端服务端模型

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

  1. 客户端先发送请求到服务端

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

  3. 服务端返回响应:发送业务处理结果

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

在这里插入图片描述

Socket套接字

概念

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

套接字分类

  1. 流套接字:使用传输层TCP协议,对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。
  2. 数据报套接字:使用传输层UDP协议,对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1个字节。
  3. 原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

Java数据报套接字通信模型

在这里插入图片描述

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

在这里插入图片描述

Java流套接字通信模型

在这里插入图片描述

UDP数据报套接字编程

DatagramSocket API

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

DatagramSocket 构造方法:

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

DatagramSocket 方法:

方法签名方法说明
void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p)从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

DatagramPacket API

DatagramPacket是UDP Socket发送和接收的数据报。

DatagramPacket 构造方法:

方法签名方法说明
DatagramPacket(byte[] buf, int length)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组
DatagramPacket(byte[] buf,int offset,int length,SocketAddress address)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组。address指定目的主机的IP和端口号

DatagramPacket 方法

InetAddress
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端的ip
int getPort()接收端主机IP地址从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端的主机和端口号
byte[] getData()取接收端主机端口号获取数据报中的数据

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

InetSocketAddress API

InetSocketAddress ( SocketAddress 的子类 )构造方法:

方法签名方法说明
InetSocketAddress(InetAddress addr, int port)创建一个Socket地址,包含IP地址和端口号
UDP客户端服务器回显服务程序

回显程序就是客户端向服务端发送什么,服务端就返回给客户端什么,就像在夜深人静的时候,你突然说了一句话,然后无形你听到了一句一模一样你刚说的话。

客户端代码设计

  1. .创建客户端DatagramSocket
  2. 准备要发送的数据
  3. .组装要发送的UDP数据报,包含数据,及发送的服务端信息
  4. 发送UDP数据报

代码示例

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {/***/private DatagramSocket clientSocket;/*** 服务器IP地址*/private String serverIp;/*** 服务器端口号*/private int serverPort;public UdpEchoClient(String ip, int port) throws SocketException {//客户端可以自己指定端口号,也可以让系统自动分配,但是自己指定的端口号可能已经被使用了,所以系统分配端口号更好this.clientSocket = new DatagramSocket();this.serverIp = ip;this.serverPort = port;}/*** 启动客户端* @throws IOException*/public void start() throws IOException {//1. 获取用户输入的数据Scanner sc = new Scanner(System.in);while (true) {System.out.print("请输入需要发送的数据->");String request = sc.next();//2. 根据用户输入的数据,将数据打包,待发送DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(serverIp), serverPort);// 3.发送数据clientSocket.send(requestPacket);// 4.接收请求DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);clientSocket.receive(responsePacket);String response = new String(responsePacket.getData(), 0, responsePacket.getLength(), "UTF-8");System.out.printf("我的请求: %s, 它的回应: %s\n", request, response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
}

服务端代码设计

  1. 创建服务端DatagramSocket
  2. 创建数据报,用于接收客户端发送的数据
  3. 等待客户端数据,一旦得到构造数据报
  4. 返回数据

代码示例

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {/***  准备好socket实例,准备传输*/private DatagramSocket serverSocket;/***指定端口* @param port* @throws SocketException*/public UdpEchoServer(int port) throws SocketException {this.serverSocket = new DatagramSocket(port);}/*** 启动服务器* @throws IOException*/public void start() throws IOException {System.out.println("服务器准备就绪!");while (true) {//1. 读取客户端的请求DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);//参数为储存数据的数组与最大空间大小serverSocket.receive(requestPacket);//2. 解析收到的数据包,一般解析成字符串进行处理String request = new String(requestPacket.getData(), 0, requestPacket.getLength(), "UTF-8");//3. 处理请求String response = process(request);//4. 发送请求,因为数据的传输是依据DatagramPacket来进行传输的,所以我们需要先包装在发送//除此之外,我们还需要知道客户端的地址和端口号//接收DatagramPacket对象时。该对象里面存有客户端的地址和端口号。可以使用getSocketAddress方法获取DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());serverSocket.send(responsePacket);//5. 输出发送日志System.out.printf("[%s:%d] 收到的请求: %s, 回应: %s\n",requestPacket.getAddress().toString(), requestPacket.getPort(), request, response);}}/*** .处理数据,回显服务直接将原数据返回即可* @param data* @return*/public String process(String data) {return data;}public static void main(String[] args) throws IOException {UdpEchoServer udpEchoServer = new UdpEchoServer(9090);udpEchoServer.start();}
}

运行结果:
在这里插入图片描述

在这里插入图片描述

UDP客户端服务器简单翻译服务程序

翻译其实就是利用了哈希表,我们只需要将中文中的词和英文中相对应意思的词一一对应,全部存放在哈希表中,这样就 构成了一个词库。当需要将中文翻译好成英文的时候,就只需要在哈希表中查找对应的英文。对应该程序我们只需将上述的服务端代码中的处理请求的部分稍加修改就行。

翻译服务端代码

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;public class UdpDictServer extends UdpEchoServer{//最简单的翻译处理服务器private final HashMap<String, String> dict = new HashMap<>();public UdpDictServer(int port) throws SocketException {super(port);dict.put("cat", "小猫");dict.put("dog", "小狗");dict.put("bird", "小鸟");}@Overridepublic String process(String data) {return dict.getOrDefault(data, "词库没有该单词!");}public static void main(String[] args) throws IOException {UdpDictServer server = new UdpDictServer(9090);server.start();}
}

运行结果:
在这里插入图片描述
在这里插入图片描述

TCP流套接字编程

ServerSocket API

ServerSocket 是创建TCP服务端Socket的API。

ServerSocket 构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

ServerSocket 方法

方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

方法签名方法说明
Socket(String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

Socket 方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

TCP客户端服务器回显服务程序

TCP和UDP不同,TCP是需要建立连接,并且通过对文件读写的方式以字节为单位进行传输。对于TCP传输,java 中提供了2个类来进行数据的传输,一个是ServerSocket,用于服务端接受客户端的连接,另一个是Socket,用于服务端和客户端之间的通信。

TCP客户端服务器简单翻译服务程序

客户端程序设计:

  1. 创建Socket对象
  2. 初始化服务端的ip和端口
  3. 启动客户端,发送数据并接收返回数据

示例代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {/*** 创建Socket对象*/private Socket socket;/**** @param serverIP  服务端ip* @param serverPort 服务端口* @throws IOException*/public TcpEchoClient(String serverIP, int serverPort) throws IOException {socket = new Socket(serverIP, serverPort);}/*** 启动客户端*/public void start() {System.out.println("客户端启动成功!");//用户输入数据Scanner input = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream()) {try (OutputStream outputStream = socket.getOutputStream()) {while (true) {//请输入数据System.out.print("请输入需要传输的数据!->");String request = input.next();//发送数据PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);//刷新缓冲区printWriter.flush();//接收回应Scanner receiverScanner = new Scanner(inputStream);String response = receiverScanner.next();//输出数据System.out.printf("我的请求:%s 它的回应:%s\n", request, response);}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9092);client.start();}
}

服务端设计:

  1. 创建socket对象,初始化端口
  2. 接收客户端的数据,返回客户端的数据。

示例代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoServer {/***  创建socket对象*/private ServerSocket serverSocket;/***  初始化服务端端口*/public TcpEchoServer(int port) throws IOException {this.serverSocket = new ServerSocket(port);}/*** 启动服务器* @throws IOException*/public void start() throws IOException {System.out.println("服务器准备就绪!");while (true) {// 3. 接收客户端的数据Socket clientSocket = serverSocket.accept();// 4. 接收 处理 回应数据processContain(clientSocket);}}private void processContain(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 服务器正式与客户端建立连接!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());try (InputStream inputStream = clientSocket.getInputStream()) {try (OutputStream outputStream = clientSocket.getOutputStream()) {//接收数据 使用Scanner比InputStream的原生方法read更方便Scanner receiveScanner = new Scanner(inputStream);while (true) {if (!receiveScanner.hasNext()) {System.out.printf("[%s:%d] 服务器与客户端已经断开连接!\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}String request = receiveScanner.next();//处理数据String response = process(request);//发送数据,为了方便,我们可以使用PrintWriter类将OutputStream类对象包裹起来,就是用来把数据打印到文件里面PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);//及时刷新缓冲区printWriter.flush();//输出回应信息System.out.printf("[%s:%d] 收到的请求: %s  回应: %s\n", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);}}}catch (IOException e) {e.printStackTrace();} finally {//释放资源 相当于挂断电话clientSocket.close();}}public String process(String data) {return data;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9092);server.start();}
}

运行结果:
在这里插入图片描述
在这里插入图片描述

上述服务端代码无法处理多个客户端的请求,因为每次建立连接服务端只能和一个客户端连接,当服务端和客户端建立连接后,处理数据会进入processContain方法,如果此时又有一个客户端尝试建立连接发送数据,就无法跳出processContain中的循环去建立新的连接,导致客户端和服务端连接不上,为了解决上述问题,可以使用线程,每次建立连接就分配一个线程去处理该连接。

线程版服务端代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoServer {/***  创建socket对象*/private ServerSocket serverSocket;/***  初始化服务端端口*/public TcpEchoServer(int port) throws IOException {this.serverSocket = new ServerSocket(port);}/*** 启动服务器* @throws IOException*/public void start() throws IOException {System.out.println("服务器准备就绪!");while (true) {// 3. 接收客户端的数据Socket clientSocket = serverSocket.accept();// 4. 接收 处理 回应数据Thread t= new Thread(() -> {try {processContain(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}});t.start();}}private void processContain(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 服务器正式与客户端建立连接!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());try (InputStream inputStream = clientSocket.getInputStream()) {try (OutputStream outputStream = clientSocket.getOutputStream()) {//接收数据 使用Scanner比InputStream的原生方法read更方便Scanner receiveScanner = new Scanner(inputStream);while (true) {if (!receiveScanner.hasNext()) {System.out.printf("[%s:%d] 服务器与客户端已经断开连接!\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}String request = receiveScanner.next();//处理数据String response = process(request);//发送数据,为了方便,我们可以使用PrintWriter类将OutputStream类对象包裹起来,就是用来把数据打印到文件里面PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);//及时刷新缓冲区printWriter.flush();//输出回应信息System.out.printf("[%s:%d] 收到的请求: %s  回应: %s\n", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);}}}catch (IOException e) {e.printStackTrace();} finally {//释放资源 相当于挂断电话clientSocket.close();}}public String process(String data) {return data;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9092);server.start();}
}

运行结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

server.png)]TCP客户端服务器简单翻译服务程序

该逻辑和UDP实现一致

示例代码

import java.io.IOException;
import java.util.HashMap;public class TcpDictServer extends TcpEchoServer{private final HashMap<String, String> dict = new HashMap<>();public TcpDictServer(int port) throws IOException {super(port);dict.put("cat", "小猫");dict.put("dog", "小狗");}@Overridepublic String process(String data) {return dict.getOrDefault(data, "词库为找到该单词!");}public static void main(String[] args) throws IOException {TcpDictServer server = new TcpDictServer(9092);server.start();}
}

运行结果:
在这里插入图片描述

TCP中的长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

  • 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。

  • 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

对比以上长短连接,两者区别如下:

  • 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。

  • 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。

  • 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等.

一发一收(短连接)

以下为一个客户端一次数据发送,和服务端多次数据接收(一次发送一次接收,可以接收多次),即只有客户端请求,但没有服务端响应的示例:

TCP服务端

示例代码

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class TcpServer {//服务器socket要绑定固定的端口private static final int PORT = 8888;public static void main(String[] args) throws IOException {// 1.创建一个服务端ServerSocket,用于收发TCP报文ServerSocket server = new ServerSocket(PORT);// 不停的等待客户端连接while (true) {System.out.println("------------------------------------------------ ---");System.out.println("等待客户端建立TCP连接...");// 2.等待客户端连接,注意该方法为阻塞方法Socket client = server.accept();System.out.printf("客户端IP:%s%n",client.getInetAddress().getHostAddress());System.out.printf("客户端端口号:%s%n", client.getPort());// 5.接收客户端的数据,需要从客户端Socket中的输入流获取System.out.println("接收到客户端请求:");InputStream is = client.getInputStream();// 为了方便获取字符串内容,可以将以上字节流包装为字符流BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));String line;// 一直读取到流结束:TCP是基于流的数据传输,一定要客户端关闭Socket输出流才表示服务端接收IO输入流结束while ((line = br.readLine()) != null) {System.out.println(line);}// 6.双方关闭连接:服务端是关闭客户端socket连接client.close();}}
}

如果没有客户端请求,此时代码是阻塞等待在 server.accept() 代码行,直到有新的客户端申请建立连接。

TCP客户端

示例代码

import java.io.*;
import java.net.Socket;public class TcpClient {//服务端IP或域名private static final String SERVER_HOST = "localhost";//服务端Socket进程的端口号private static final int SERVER_PORT = 8888;public static void main(String[] args) throws IOException {// 3.创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接Socket client = new Socket(SERVER_HOST, SERVER_PORT);// 4.发送TCP数据,是通过socket中的输出流进行发送OutputStream os = client.getOutputStream();// 为了方便输出字符串作为发送的内容,可以将以上字节流包装为字符流PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));// 4-1.发送数据:pw.println("hello world!");// 4-2.有缓冲区的IO操作,真正传输数据,需要刷新缓冲区pw.flush();// 7.双方关闭连接:客户端关闭socket连接client.close();}
}

运行结果:

在这里插入图片描述
在这里插入图片描述

客户端向服务端发送数据后就会重新断开连接,而服务端不会断开会等待下一个客户端的连接。


各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

在这里插入图片描述

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

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

相关文章

一文读懂c++语言

一文读懂C语言 C的发展C的设计目标C的特性C的挑战 C的发展 C是一种通用的、高级的编程语言&#xff0c;它是C语言的扩展。C由Bjarne Stroustrup于1983年首次引入&#xff0c;并在之后的几十年中不断发展壮大。C被广泛应用于各种领域&#xff0c;包括系统开发、游戏开发、嵌入式…

开启MySQL的binlog日志

1.判断MySQL是否已经开启binlog SHOW VARIABLES LIKE log_bin; 查看MySQL的binlog模式 show global variables like "binlog%";几个关于binlog常用的命令 #查看日志开启状态 show variables like log_%; #查看所有binlog日志列表 show master logs; #查看最新一个b…

mac安装open3d时候出现错误

在测试open3d是否正常顺利安装时&#xff0c;出现了如下错误&#xff1a; python -c "import open3d as o3d; print(o3d.__version__)" Traceback (most recent call last):File "<string>", line 1, in <module>File "/Users/huangzhe/…

python——案例18:判断该元素是否在列表中

案例18&#xff1a;判断该元素是否在列表中test_list[10,-8,25.6,88,0,4]print("查看88是否在列表里面&#xff1a;")for i in test_list:if(i88):print("存在") print("查看88是否在列表中&#xff1a;") if(88 in test_list):print("存在…

监控Kubernetes 控制面组件的关键指标

控制面组件的监控&#xff0c;包括 APIServer、Controller-manager&#xff08;简称 CM&#xff09;、Scheduler、etcd 四个组件。 1、APIServer APIServer 的核心职能是 Kubernetes 集群的 API 总入口&#xff0c;Kube-Proxy、Kubelet、Controller-Manager、Scheduler 等都需…

【Java】 java | git | win系统重装会给开发环境带来哪些问题

一、概述 1、近期发现电脑用起来不丝滑了&#xff0c;文件夹操作卡顿&#xff0c;一阵操作还会蓝屏 2、不能忍&#xff0c;整理排查 二、电脑情况 1、CPU&#xff1a; I5-9400F 2.9GHz 6核 2、内存&#xff1a; 32G 3、固态&#xff1a;256G 4、机械&#xff1a;1T 5、盘符使用…

机器学习深度学习——RNN的从零开始实现与简洁实现

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——循环神经网络RNN &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮…

R语言5_安装Giotto

环境Ubuntu22/20, R4.1. 已开启科学上网。 第一步&#xff0c;更新服务器环境&#xff0c;进入终端&#xff0c;键入如下命令&#xff0c; apt-get update apt install libcurl4-openssl-dev libssl-dev libxml2-dev libcairo2-dev libgtk-3-dev libhdf5-dev libmagick9-dev …

【Java多线程学习7】Java线程池技术

线程池技术 一、什么是线程池 线程池顾名思义是管理一组线程的池子。当有任务要处理时&#xff0c;直接从线程池中获取线程来处理&#xff0c;处理完之后线程不会立即销毁&#xff0c;而是等待下一个任务。 二、为什么要使用线程池? 线程池的作用&#xff1f; 1、降低资源…

Javascript 数据结构[入门]

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于海外某世界知名高校就读计算机相关专业。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。…

数据结构-栈和队列

目录 栈的概念 栈的使用 ​编辑 模拟实现栈 中缀表达式转后缀表达式 括号匹配 出栈入栈次序匹配 队列概念 队列的使用 栈的概念 栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作.进行数据插入和删除操作的一端称为栈顶,;另一端称为栈底.栈中的数据…

【强化学习】值函数算法DQNs详解【Vanilla DQN Double DQN Dueling DQN】

DQNs【Vanilla DQN & Double DQN & Dueling DQN】 文章目录 DQNs【Vanilla DQN & Double DQN & Dueling DQN】1. DQN及其变种介绍1.1 Vanilla DQN1.2 Double DQN1.3 Dueling DQN 2. Gym环境介绍2.1 Obseravtion Space2.2 Reward Function2.3 Action Space 3. D…

【Docker晋升记】No.2 --- Docker工具安装使用、命令行选项及构建、共享和运行容器化应用程序

文章目录 前言&#x1f31f;一、Docker工具安装&#x1f31f;二、Docker命令行选项&#x1f30f;2.1.docker run命令选项&#xff1a;&#x1f30f;2.2.docker build命令选项&#xff1a;&#x1f30f;2.3.docker images命令选项&#xff1a;&#x1f30f;2.4.docker ps命令选项…

Unity 编辑器资源导入处理函数 OnPostprocessAudio :深入解析与实用案例

Unity 编辑器资源导入处理函数 OnPostprocessAudio 用法 点击封面跳转下载页面 简介 在Unity中&#xff0c;我们可以使用编辑器资源导入处理函数&#xff08;OnPostprocessAudio&#xff09;来自定义处理音频资源的导入过程。这个函数是继承自AssetPostprocessor类的&#xff…

MyBatis的XML映射文件

Mybatis的开发有两种方式&#xff1a; 注解 XML配置文件 通过XML配置文件的形式来配置SQL语句&#xff0c;这份儿XML配置文件在MyBatis当中也称为XML映射文件。 导学&#xff1a;在MyBatis当中如何来定义一份儿XML映射文件&#xff1f; 在MyBatis当中&#xff0c;定义XML…

python编辑器安装与配置,python用哪个编辑器好用

大家好&#xff0c;给大家分享一下python编辑器pycharm安装教程&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 哪些python的编程软件值得推荐&#xff1f; 编写python源代码的软件.首推的Pycharm。 PyCharm用于bai一般IDE具备的功能&…

VS2015+cublas实操记录(cuda加速GEMM矩阵乘加算子)

1. 环境配置&#xff1a; cuda安装后一般的安装位置在&#xff1a;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8 把这个目录下的include和lib分别配置在vs中&#xff0c;安装cuda教程可参考&#xff1a;https://zhuanlan.zhihu.com/p/520995962&#xff08;笔者…

Reinforcement Learning with Code 【Chapter 10. Actor Critic】

Reinforcement Learning with Code 【Chapter 10. Actor Critic】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of …

iview 日期 datetimerange

问题&#xff1a;每次点击编辑按钮进入到编辑页面&#xff0c;活动时间明明有值&#xff0c;却还是提示请选择活动时间。 原因&#xff1a;值没绑定上 解决办法&#xff1a;v-model 修改为 :value <Form-item label"活动时间" prop"timeRange"><d…

VUE+ElementUI的表单验证二选一必填项,并且满足条件后清除表单验证提示

上代码 <el-form-item label"出库单号" prop"ecode" ref"ecode" :rules"rules.ecode"><el-input v-model"queryParams.ecode" placeholder"出库单号和出库箱号至少填写一项" clearable style"width…