2. 网络之网络编程
网络编程
文章目录
- 网络编程
- 1. UDP
- 1.1 DatagramSocket
- 1.1.1 DatagramSocket 构造方法
- 1.1.2 DatagramSocket 方法:
- 1.2 DatagramPacket
- 1.2.1 DatagramPacket构造方法
- 1.2.2 DaragramPacket方法
- 1.2.3InetSocketAddress API
- 1.3 UDP回显服务器
- 1.3.1 框架结构
- 1.3.2 读取请求并解析
- 1.3.3 根据请求构建响应
- 1.3.4 响应发回客户端
- 1.3.5 打印日志
- 1.3.6 完整程序
- 1.4 UDP回显客户端
- 1.4.1构建框架
- 1.4.2 控制台读取数据构建请求
- 1.4.3 发送请求
- 1.4.4 接收响应
- 1.4.5 输出响应
- 1.4.6 完整代码
- 2. TCP
- 2.1 ServerSocket
- 2.1.1ServerSocket 构造方法
- 2.1.2 ServerSocket 方法
- 2.2 Socket
- 2.2.1 Socket 构造方法
- 2.2.2 Socket 方法
- 2.3 TCP回显服务器
- 2.4 TCP 回显客户端
- 3. UDP和TCP的异同
- 3.1 异
- 3.2 同
- 4. 部署至云服务器
- 4.1 打包
- 4.2 上传
- 4.3 执行
- 4.4 问题总结:
网络编程是使用 IP地址,或域名,和 端口连接到另一台计算机上对应的程序,按照规定的 协议 (数据格式)来交换数据,实际编程中建立连接和发送、接收数据在语言级已经实现,做的更多的工作是设计协议,以及编写生成和解析数据的代码罢了,然后把数据转换成逻辑的结构显示或控制逻辑即可。
网络编程的三要素
- IP 地址: 用于标识网络设备的网络地址。
- 端囗: 应用程序在设备中唯一的标识,对不同应用程序进行区分。
- 协议:数据在网络中传输(传输层)的规则,其中最主要的UDP协议和TCP协议。
- TCP:用户传输协议
- UDP:用户数据报协议
我们这里的重点不在于介绍UDP、TCP协议的内容,而是关注Java中使用UDP、TCP协议(传输层)进行数据传输,并且通过这两个传输层协议完成基础的回显服务器、客户端的编写
1. UDP
1.1 DatagramSocket
DatagramSocket是UDP Socket,用于发送和接收UDP数据报。我们使用这个类来完成UDP数据传输。
1.1.1 DatagramSocket 构造方法
方法签名 | 方法说明 |
---|---|
DatagramSocket() | 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端) |
DatagramSocket(int) | 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端) |
-
DatagramSocket()
操作系统会随机分配一个空闲的端口 -
DatagramSocket(int)
port 传入一个端口号(1024~65535),
DatagramSocket类提供了两个版本,一个带端口(port)一个不带,而带端口的一般用于服务器端,不带端口的一般用于客户端。由于服务端端口的占用情况未知,一般交给操作系统(OS)自动分配,而服务器这边的端口占用情况开发人员一般会比较清楚,所以会手动指定。
1.1.2 DatagramSocket 方法:
方法签名 | 方法说明 |
---|---|
void receive(DatagramPacket p) | 从此套接字接收数据报(如果没有接收到数据报,该法会阻塞等待) |
void send(DatagramPacketp) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
void close() | 关闭此数据报套接字 |
receive(DatagramPacket p)
这里的p是输出型参数,内部会将数据填入p中send(DatagramPacketp)
用来发送数据报,数据要提前存放在DatagramPacket对象中close()
使用完后请记得关闭!!!
1.2 DatagramPacket
DatagramPacket是UDP Socket发送和接收的数据报,UDP是面向数据报的。
1.2.1 DatagramPacket构造方法
方法签名 | 方法说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造一个DatagramPacket 用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length) |
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) | 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号 |
DatagramPacket(byte[] buf, int length)
指定byte数组作为缓冲区,length是要存放的长度DatagramPacket(byte[] buf, int offset, int length,SocketAddress address)
比上面多路一个offset(偏移量)和address,offset表示从第几个字节开始填充,address表示ip地址和端口号。
1.2.2 DaragramPacket方法
InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号 |
byte[] getData() | 获取数据报中的数据 |
InetSddress getAddress()
获取IP地址int getPort()
获取端口
-byte[] getData()
获取数据报中的数据
构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。
1.2.3InetSocketAddress API
方法签名 | 方法说明 |
---|---|
InetSocketAddress(InetAddress addr, int port) | 创建一个Socket地址,包含IP地址和端口号 |
了解了上面这两个类我们就可以在Java中利用UDP来编写一个回显程序。
1.3 UDP回显服务器
1.3.1 框架结构
首先搭建服务器程序的基本框架,并在构造方法中创建出一个DatagramSocket对象。构造时要传入一个端口号,因为在网络通信中,服务器是被动方,如果端口号为随机,那么此时客户端就不知道服务器的端口号,也就无法进行通信了。
public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() {}
}
接着在start中实现具体的服务器代码,首先是一个while(true)循环包含整个方法体,因为大多数服务器7*24小时运行,不断处理客户端发送的请求,返回响应。
1.3.2 读取请求并解析
// receive 方法的参数是一个输出型参数
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
// 如果客户端发来了请求,receive就能顺利读出来请求,如果没有请求就会进入阻塞
socket.receive(requestPacket);
// 将数组中的数据转化为字符串,方便读取
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
1.3.3 根据请求构建响应
String response = process(request);// .......public String process(String request) {return request;}
1.3.4 响应发回客户端
// 此处DatagramPacket 的参数就不能是空的数组了,因为要将响应的字符串返回去
// send的参数也是DatagramPacket
// 在receive时,requestPacket中已经存放了 客户端的IP地址和端口号
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
socket.send(responsePacket);
1.3.5 打印日志
System.out.printf("[%s:%d] req: %s;resp : %s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
// 日志格式 - 客户端的IP,客户端的端口号,请求,响应
1.3.6 完整程序
package UDPEchoServer;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {// 创建一个DatagramSocket对象,操作网卡private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {// 服务器端手动分配端口 - 只申请了一个socket对象,一直使用到结束不用close()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后数据是以二进制存储到requestPacket中// 想要显示出这里的请求,还需要将这里的字节数组够造成字符串// getLength() 拿到的是收到的数据的真实长度(字节数)String request = new String(requestPacket.getData(),0,requestPacket.getLength());// 2. 根据请求计算响应(业务)String response = process(request);// 3. 把响应写会客户端// 响应对象DatagramPacket ,构造好响应数据,再通过send发送【指定数据和目的地(无连接)】DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);// 打印日志,把这次交互的详情打印出来System.out.printf("[%s,%d] req=%s, req=%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}public String process(String request) {// 当前是echo server 请求即响应return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(5265);// port range :1023 ~ 65535 server.start();}
}
1.4 UDP回显客户端
1.4.1构建框架
构建客户端的基本框架,相比于服务器,客户端在构造方法处还需要传入服务器的端口号和IP。
public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP = null;private int serverPort = 0;public UdpEchoClient(String serverIP,int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() {}
}
1.4.2 控制台读取数据构建请求
Scanner scanner = new Scanner(System.in);System.out.print("->");
String request = scanner.next();
// 判断是否要退出
if(request.equals("exit")) {System.out.println("goodbye");break;
}
1.4.3 发送请求
// 构造一个 DatagramPacket 对象 此时该对象的参数要传入客户端的 IP(serverIP) 和 端口(serverPort)
// 此处的IP需要使用getByName()方法
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIP),serverPort);
socket.send(requestPacket);
1.4.4 接收响应
DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
String response = new String(responsePacket.getData(),0,responsePacket.getLength());
1.4.5 输出响应
System.out.println(response);
1.4.6 完整代码
package UDPEchoServer;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp = "";private int serverPort = 0;public UdpEchoClient(String ip, int port) throws SocketException {// 系统自动分配客户端端口socket = new DatagramSocket();this.serverIp = ip;this.serverPort = port;}public void start() throws IOException {System.out.println("客户端启动!!!");Scanner scanner = new Scanner(System.in);while (true) {// 1. 从控制台读取数据,作为请求System.out.print("-> ");String request = scanner.next();// 2. 把请求够造成DatagramPacket对象DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);// 3. 发送请求socket.send(requestPacket);// 4. 尝试读取响应DatagramPacket responPacket = new DatagramPacket(new byte[4096],4096);socket.receive(responPacket);// 5. 将响应转成字符串打印出来String response = new String(responPacket.getData(),0,responPacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("152.136.59.108",9090);client.start();}
}
2. TCP
2.1 ServerSocket
ServerSocket 是TCP服务端的API。
2.1.1ServerSocket 构造方法
ServerSocket 是创建TCP服务端Socket的API
方法签名 | 方法说明 |
---|---|
ServerSocket(int port) | 创建一个服务端流套接字Socket,并绑定到指定端口 |
2.1.2 ServerSocket 方法
方法签名 | 方法说明 |
---|---|
Socket accept() | 开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端 Socket 对象,并基于该Socket建立与客户端的连接,否则阻塞等待 |
void close() | 关闭此套接字 |
2.2 Socket
Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
2.2.1 Socket 构造方法
方法签名 | 方法说明 |
---|---|
Socket(String host, int port) | 创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接 |
2.2.2 Socket 方法
方法签名 | 方法说明 |
---|---|
InetAddress getInetAddress() | 返回套接字所连接的地址 |
InputStream getInputStream() | 返回此套接字的输入流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
2.3 TCP回显服务器
由于流程和UDP大差不差,这里介绍一些大概步骤,然后给出所有代码。
-
读取请求并解析
-
根据请求构造响应
-
响应返回客户端
-
打印日志
完整代码
package network;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;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");ExecutorService service = Executors.newCachedThreadPool();while (true) {// 通过 accept 方法, 把内核中已经建立好的连接拿到应用程序中.// 建立连接的细节流程都是内核自动完成Socket clientSocket = serverSocket.accept();// 使用线程池.service.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}}// 通过这个方法, 来处理当前的连接.public void processConnection(Socket clientSocket) {// 进入方法, 先打印一个日志, 表示当前有客户端连上了.System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());// 接下来进行数据的交互.try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 使用 try ( ) 方式, 避免后续用完了流对象, 忘记关闭.// 由于客户端发来的数据, 可能是 "多条数据", 针对多条数据, 就循环的处理.while (true) {Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()) {// 连接断开了. 此时循环就应该结束System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort());break;}// 1. 读取请求并解析. 此处就以 next 来作为读取请求的方式. next 的规则是, 读到 "空白符" 就返回.String request = scanner.next();// 2. 根据请求, 计算响应.String response = process(request);// 3. 把响应写回到客户端.// 可以把 String 转成字节数组, 写入到 OutputStream// 也可以使用 PrintWriter 把 OutputStream 包裹一下, 来写入字符串.PrintWriter printWriter = new PrintWriter(outputStream);// 此处的 println 不是打印到控制台了, 而是写入到 outputStream 对应的流对象中, 也就是写入到 clientSocket 里面.// 此处使用 println 带有 \n 也是为了后续 客户端这边 可以使用 scanner.next 来读取数据.printWriter.println(response);// 刷新缓冲区. 如果没有刷新操作, 可能数据仍然是在内存中, 没有被写入网卡.printWriter.flush();// 4. 打印一下这次请求交互过程的内容System.out.printf("[%s:%d] req=%s, resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(),request, response);}} catch (IOException e) {e.printStackTrace();} finally {try {// 在这个地方, 进行 clientSocket 的关闭.// processConnection 就是在处理一个连接. 这个方法执行完毕, 这个连接也就处理完了.clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {// 此处也是写的回显服务器. 响应和请求是一样的.return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}
2.4 TCP 回显客户端
同样,这里也是给出流程和完整代码。
-
控制台读取数据构建请求
-
发送请求
-
接收响应
-
打印日志
完整代码
package network;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 {private Socket socket = null;public TcpEchoClient(String serverIp, int serverPort) throws IOException {// 需要在创建 Socket 的同时, 和服务器 "建立连接", 此时就得告诉 Socket 服务器在哪里~~// 具体建立连接的细节, 不需要咱们代码手动干预. 是内核自动负责的.// 当我们 new 这个对象的时候, 操作系统内核, 就开始进行 三次握手 具体细节, 完成建立连接的过程了.socket = new Socket(serverIp, serverPort);}public void start() {// tcp 的客户端行为和 udp 的客户端差不多.// 都是:// 3. 从服务器读取响应.// 4. 把响应显示到界面上.Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {PrintWriter writer = new PrintWriter(outputStream);Scanner scannerNetwork = new Scanner(inputStream);while (true) {// 1. 从控制台读取用户输入的内容System.out.print("-> ");String request = scanner.next();// 2. 把字符串作为请求, 发送给服务器// 这里使用 println, 是为了让请求后面带上换行.// 也就是和服务器读取请求, scanner.next 呼应writer.println(request);writer.flush();// 3. 读取服务器返回的响应.String response = scannerNetwork.next();// 4. 在界面上显示内容了.System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}
}
3. UDP和TCP的异同
3.1 异
- UDP 是无连接的,TCP是有连接的
- UDP 是不可靠传输的,TCP是可靠传输的
- UDP 是面向数据报的,TCP是面向字节流的
3.2 同
UDP 和 TCP都是全双工的,什么是全双工?一个信道既可以接收数据又可以发送数据就是全双工的。
4. 部署至云服务器
4.1 打包
这里就使用IDE进行打包(jar包)
此时就会多出一个out目录,这个目录下artifacts目录下就会有jar包
4.2 上传
将程序上传到云服务器上。
4.3 执行
启动服务端程序!!!
java -jar Network.jar
最后就可以在其他计算机上运行客户端来访问到这个回显程序服务器了。
4.4 问题总结:
记得将你使用的端口在云服务器控制台放行,不然可能也访问不了。
如果没有安装java环境,请执行以下命令安装环境
yum install java
如果本篇文章对你有帮助,请点赞、评论、转发,你的支持是我创作的动力。
相关文章:

2. 网络之网络编程
网络编程 文章目录 网络编程1. UDP1.1 DatagramSocket1.1.1 DatagramSocket 构造方法1.1.2 DatagramSocket 方法: 1.2 DatagramPacket1.2.1 DatagramPacket构造方法1.2.2 DaragramPacket方法1.2.3InetSocketAddress API 1.3 UDP回显服务器1.3.1 框架结构1.3.2 读取请…...

工作数字化的中国历程 | 从 OA 到 BPM 到数字流程自动化
业务流程是由“活动”(或称“工作任务”)构成的,在企业里的所有工作是不是都叫流程,或者属于流程的一部分,这个概念很绕,我觉得没有必要去做学究气的辨析。我曾经提出过一个从工作的两个特性(产…...

6-1 二叉排序树查找操作
description 本题要求实现二叉排序树的查找操作。 函数接口定义: BSTree SearchBST(BSTree T,ElemType e); 其中BSTree结构定义如下: typedef int ElemType; typedef struct BSTNode { ElemType data; struct BSTNode *lchild,*rchild; }BSTNode,*BS…...

服务上千家企业,矩阵通2.0重磅上线,全链路管理新媒体矩阵
自上线以来 矩阵通已服务了上千家企业级客户 覆盖汽车、家居、媒体、金融、教育等多个行业 矩阵通1.0时代 我们以“数据”为基座打造出10功能 帮助企业轻松管理新媒体矩阵 实现账号管理、数据分析、竞对监测、 人员考核、风险监管等需求 而现在 矩阵通2.0重磅上线 新增…...

【代码随想录】算法训练计划11
1、20. 有效的括号 题目: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号…...

Jmeter之JSR223
一、JSR223组件 JSR是Java Specification Requests的缩写,意思是Java规范提案。JSR已成为Java界的一个重要标准. JSR223其实包含了有好几种组件,但是其用法都是一致的,并且都是执行一段代码,主要分类如下: JSR223 PreProcessor JSR223 Timer JSR223 S…...

c++23中的新功能之十八新增的属性
一、c23新的属性 在前面的分析中说过,各种语言的发展整体思路是一致的,即朝着更加实用、简单和更接近自然语言的方向在前进。c23中也在不断的完善和增加相关开发的一些属性和预编译处理指令,这样就可以让开发者在开发的过程中对程序进行控制…...

动手学深度学习:1.线性回归从0开始实现
动手学深度学习:1.线性回归从0开始实现 1.手动构造数据集2.小批量读取数据集3.初始化模型参数4.定义模型和损失函数5.小批量随机梯度下降更新6.训练完整代码 1.手动构造数据集 根据带有噪声的线性模型构造一个人造数据集,任务是使用这个有限样本的数据集…...

【计算机网络】应用层
应用层协议原理 客户-服务器体系结构: 特点:客户之间不能直接通信;服务器具有周知的,固定的地址,该地址称为IP地址。 配备大量主机的数据中心常被用于创建强大的虚拟服务器;P2P体系结构: 特点&…...

python 深度学习 解决遇到的报错问题9
本篇继python 深度学习 解决遇到的报错问题8-CSDN博客 目录 一、can only concatenate str (not "int") to str 二、cant convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, complex64, complex128, int64, in…...

能源管理系统为什么选择零代码开发平台?
市面上有很多能源管理系统,但是零代码开发能源管理系统却非常少。那为什么推荐选择零代码开发平台呢?因为很多企业缺少技术人员,但是却仍然需要数字化工具和流程推进业务和项目,解决能源管理技术人员不懂代码的矛盾问题࿰…...

【LeetCode】剑指 Offer Ⅱ 第8章:树(12道题) -- Java Version
题库链接:https://leetcode.cn/problem-list/e8X3pBZi/ 类型题目解决方案二叉树的深搜剑指 Offer II 047. 二叉树剪枝递归(深搜):二叉树的后序遍历 (⭐)剑指 Offer II 048. 序列化和反序列化二叉树递归&…...

利用maven的dependency插件将项目依赖从maven仓库中拷贝到一个指定的位置
https://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html 利用dependency:copy-dependencies可以将项目的依赖从maven仓库中拷贝到一个指定的位置。 使用默认配置拷贝依赖 如果直接执行mvn dependency:copy-dependencies,是将项目…...

在Flask中实现文件上传七牛云中并下载
在Flask中实现文件上传和七牛云集成 文件上传是Web应用中常见的功能之一,而七牛云则提供了强大的云存储服务,使得文件存储和管理变得更加便捷。在本篇博客中,我们将学习如何在Flask应用中实现文件上传,并将上传的文件保存到七牛云…...

【Linux】centOS7安装配置及Linux的常用命令---超详细
一,centOS 1.1 centOS的概念 CentOS(Community Enterprise Operating System)是一个由社区支持的企业级操作系统,它是以Red Hat Enterprise Linux(RHEL)源代码为基础构建的。CentOS提供了一个稳定、可靠且…...

【ES专题】ElasticSearch搜索进阶
目录 前言阅读导航前置知识特别提醒笔记正文一、分词器详解1.1 基本概念1.2 分词发生的时期1.3 分词器的组成1.3.1 切词器:Tokenizer1.3.2 词项过滤器:Token Filter1.3.3 字符过滤器:Character Filter 1.4 倒排索引的数据结构 <font color…...

【iOS免越狱】利用IOS自动化WebDriverAgent实现自动直播间自动输入
1.目标 由于看直播的时候主播叫我发 666,支持他,我肯定支持他呀,就一直发,可是后来发现太浪费时间了,能不能做一个直播间自动发 666 呢?于是就开始下面的操作。 2.操作环境 iPhone一台 WebDriverAgent …...

Python基础入门例程28-NP28 密码游戏(列表)
最近的博文: Python基础入门例程27-NP27 朋友们的喜好(列表)-CSDN博客 Python基础入门例程26-NP26 牛牛的反转列表(列表)-CSDN博客 Python基础入门例程25-NP25 有序的列表(列表)-CSDN博客 目录…...

乌班图 Linux 系统 Ubuntu 23.10.1 发布更新镜像
Ubuntu 团队在其官网上发布了Ubuntu 23.10.1 版本,这是目前较新的 Ubuntu 23.10(Focal Fossa)操作系统系列的第一个发行版,旨在为社区提供最新的安装媒体。Ubuntu 22.04 LTS(Focal Fossa)操作系统系列于 2022 年 4 月 21 日发布。 Ubuntu 23.10 LTS(长期支持版本)可用…...

Java金字塔、空心金字塔、空心菱形
Java金字塔 public class TestDemo01 {public static void main(String[] args){//第一个for用于每行输出 从i1开始到i<5,总共5行for(int i1;i<5;i){//每行前缀空格,这个for用于表示每行输出*前面的空格//从上面规律可得,每行输出的空格数为总层数,…...

前端 | (十四)canvas基本用法 | 尚硅谷前端HTML5教程(html5入门经典)
文章目录 📚canvas基本用法🐇什么是canvas(画布)🐇替换内容🐇canvas标签的两个属性🐇渲染上下文 📚绘制矩形🐇绘制矩形🐇strokeRect时,边框像素渲染问题🐇添加…...

206.反转链表
206.反转链表 力扣题目链接(opens new window) 题意:反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 双双指针法: 创建三个节点 pre(反转时的第一个节点)、cur(当前指向需要反转的节点…...

SpringBoot项目从resources目录读取文件
SpringBoot 从 resources 读取文件 使用 Spring 给我们提供的工具类来进行读取 File file org.springframework.util.ResourceUtils.getFile("classpath:人物模板.docx");可能读取失败,出现如下错误: java.io.FileNotFoundException: clas…...

SQL实现根据时间戳和增量标记IDU获取最新记录和脱IDU标记
需求说明:表中有 id, info, cnt 三个字段,对应的增量表多idu增量标记字段和时间戳字段ctimestamp。增量表中的 id 会有重复,其他字段 info、cnt 会不断更新,idu为增量标记字段,ctimestamp为IDU操作的时间戳。目的时要做…...

京东数据平台:2023年9月京东智能家居行业数据分析
鲸参谋监测的京东平台9月份智能家居市场销售数据已出炉! 9月份,智能家居市场销售额有小幅上涨。根据鲸参谋电商数据分析平台的相关数据显示,今年9月,京东平台智能家居的销量为37万,销售额将近8300万,同比增…...

计算两个时间之间连续的日期(java)
背景介绍 给出两个时间,希望算出两者之间连续的日期,比如时间A:2023-10-01 00:00:00 时间B:2023-11-30 23:59:59,期望得到的连续日期为2023-10-01、2023-10-02、… 2023-11-30 Java版代码示例 import java.time.temporal.ChronoUnit; import java.tim…...

Kali Linux:网络与安全专家的终极武器
文章目录 一、Kali Linux 简介二、Kali Linux 的优势三、使用 Kali Linux 进行安全任务推荐阅读 ——《Kali Linux高级渗透测试》适读人群内容简介作者简介目录 Kali Linux:网络与安全专家的终极武器 Kali Linux,对于许多网络和安全专业人士来说&#x…...

Leetcode—101.对称二叉树【简单】
2023每日刷题(十九) Leetcode—101.对称二叉树 利用Leetcode101.对称二叉树的思想的实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool isSa…...

判断是否工作在docker环境
判断是否工作在docker环境 方式一:判断根目录下 .dockerenv 文件 docker环境下:ls -alh /.dockerenv , 非docker环境,没有这个.dockerenv文件的 注:定制化比较高的docker系统也可能没有这个文件 方式二:查询系统进程…...

文件上传学习笔记
笔记 文件上传 文件上传是指将本地图片,视频,音频等文件上传到服务器,供其它用户浏览或下载的过程 文件上传前端三要素 : file表单项 post方式 multipart/from-data 服务端接收文件 : 用spring中的API : MultipartFile 要想文件名唯一 …...