【Java】网络编程(Socket)
网络编程
Socket
我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则使用套接字Socket来进行分离
套接字就像是传输层为应用层开的一个小口,应用程序通过这个小口向远程发送数据,或者接收远程发来的数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,是不知道也不需要知道的,也不会关心它如何传输,这属于网络其他层次工作
Socket实际是传输层供给应用层的编程接口。Socket就是应用层与传输层之间的桥梁。使用Socket变成可以开发客户机和服务器的应用程序,可以在本地网络上通信,也可以通过Internet在全球范围内通信
Java网络编程中的常用类
Java为了跨平台,在网络应用通信时是不允许直接调用操作系统接口的,而是由java.net包来提供网络功能。
InetAddress的使用
作用:封装计算机的IP地址和DNS(没有端口信息)
特点:
这个类没有构造方法,如果想要得到对象,只能通过静态方法:getLocalHost() 、 getByName() 、 getALLByName() 、 getAddress() 、 getHostName()
获取本机信息
获取本机信息需要使用getLocalHost()方法创建InetAddress对象,这个对象包含了本机的IP地址,计算机名等信息
public class InetTest {public static void main(String[] args) {try {InetAddress localHost = InetAddress.getLocalHost();String hostAddress = localHost.getHostAddress();String hostName = localHost.getHostName();System.out.println(hostAddress);System.out.println(hostName);} catch (UnknownHostException e) {throw new RuntimeException(e);}}
}
根据域名获取计算机的信息
根据域名获取计算机信息时需要使用getByName(“域名”)方法创建InetAddress对象
public class InetTest2 {public static void main(String[] args) {try {InetAddress inetAddress = InetAddress.getByName("www.baidu.com");System.out.println(inetAddress.getHostAddress());System.out.println(inetAddress.getHostName());} catch (UnknownHostException e) {throw new RuntimeException(e);}}
}
根据IP地址获取计算机的信息
根据IP地址获取计算机的信息时需要使用getByName(“IP”)方法创建InetAddress对象
public class InetTest3 {public static void main(String[] args) {try {InetAddress inetAddress = InetAddress.getByName("110.242.68.4");System.out.println(inetAddress.getHostName());System.out.println(inetAddress.getHostAddress());} catch (UnknownHostException e) {throw new RuntimeException(e);}}
}
InetSocketAddress的使用
作用:包含IP和端口信息,常用于Socket通信。此类实现IP套接字地址(IP地址+端口号),不依赖任何协议
InetSocketAddress相比较InetAddress多了一个端口号,端口的作用:一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现
public class InetSocketTest {public static void main(String[] args) {InetSocketAddress inetSocketAddress = new InetSocketAddress("www.baidu.com",80);System.out.println(inetSocketAddress.getAddress().getHostAddress());System.out.println(inetSocketAddress.getHostName());}
}
URL的使用
IP地址标识了Internet上唯一的计算机,而URL则标识了这些计算机上的资源。URL代表一个资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或者搜索引擎的查询
为了方便程序员编程,JDK中提供了URL类,该类的全名是java.net.URL,有了这样一个类,就可以使用它的各种方法来对URL对象进行分割、合并等处理
public class UrlTest {public static void main(String[] args) {try {URL url = new URL("http://www.edu2act.cn/task/list/finished/");System.out.println("获取当前协议的默认端口:" + url.getDefaultPort());System.out.println("访问资源:" + url.getFile());System.out.println("主机名" + url.getHost());System.out.println("访问资源的路径:" + url.getPath());System.out.println("协议" + url.getProtocol());System.out.println("参数部分" + url.getQuery());} catch (MalformedURLException e) {throw new RuntimeException(e);}}
}
通过URL实现最简单的网络爬虫
public class UrlTest2{public static void main(String[] args)throws Exception {URL url = new URL("http://dbms.wangding.co/design/ch04-database-design-1/");try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {StringBuilder sb = new StringBuilder();String temp;while ((temp = br.readLine()) != null) {sb.append(temp);}System.out.println(sb);} catch (Exception e) {e.printStackTrace();}}
}
TCP通信的实现和项目案例
TCP通信实现原理
前边我们提到TCP协议是面向的连接的,在通信时客户端与服务器端必须建立连接。在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的程序被称作服务器端(Server)程序,简称服务器。一旦通讯建立,则客户端和服务器端完全一样,没有本质的区别。
请求-相应 模式
- Socket类:发送TCP信息
- ServerSocket类:创建服务器
套接字Socket是一种进程间的数据交换机制。这些进程既可以在同一机器上,也可以在通过网络连接的不同机器上。换句话说,套接字起到通信端点的作用。单个套接字是一个端点,而一对套接字则构成一个双向通信信道,使非关联进程可以在本地或通过网络进行数据交换。一旦建立套接字连接,数据即可在相同或不同的系统中双向或单向发送,直到其中一个端点关闭连接。套接字与主机地址和端口地址相关联。主机地址就是客户端或服务器程序所在的主机的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端口。
在客户端和服务器中,分别创建独立的Socket,并通过Socket的属性,将两个Socket进行连接,这样,客户端和服务器通过套接字所建立的连接使用输入输出流进行通信。
TCP/IP套接字是最可靠的双向流协议,使用TCP/IP可以发送任意数量的数据。
实际上,套接字只是计算机上已编号的端口。如果发送方和接收方计算机确定好端口,他们就可以通信了。
客户端与服务器端的通信关系图:
TCP/IP通信连接的简单过程
位于A计算机上的TCP/IP软件向B计算机发送包含端口号的消息,B计算机的TCP/IP软件接收该消息,并进行检查,查看是否有它知道的程序正在该端口上接收消息。如果有,他就将该消息交给这个程序。
通过Socket的编程顺序
1、创建服务器ServerSocket,在创建时,定义ServerSocket的监听端口(在这个端口接收客户端发来的消息)
2、ServerSocket调用accept()方法,使之处于阻塞状态。
3、创建客户端Socket,并设置服务器的IP及端口。
4、客户端发出连接请求,建立连接。
5、分别取得服务器和客户端Socket的InputStream和OutputStream。
6、利用Socket和ServerSocket进行数据传输。
7、 关闭流及Socket。
TCP通信入门案例
创建服务端
public class BasicSocketServer {public static void main(String[] args) throws IOException {System.out.println("服务器已启动,等待监听....");ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(8888);Socket socket = serverSocket.accept();//连接成功后会得到与客户端对应的Socket对象,并解除线程阻塞InputStream in = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(in));System.out.println(br.readLine());OutputStream out = socket.getOutputStream();} catch (IOException e) {throw new RuntimeException(e);}finally {serverSocket.close();}}
}
创建客户端
public class BasicSocketClient {public static void main(String[] args) throws IOException {Socket socket = null;PrintWriter pw = null;try {socket = new Socket("127.0.0.1",8888);OutputStream out = socket.getOutputStream();pw = new PrintWriter(out);pw.write("服务端,你好!");pw.flush();} catch (IOException e) {throw new RuntimeException(e);}finally {pw.close();socket.close();}}
}
TCP单向通信
单向通信是指通信双方中,一方固定为发送端,一方固定为接收端
创建服务端
public class OneWaySocketServer {public static void main(String[] args) {System.out.println("服务器启动,开始监听");try(ServerSocket serverSocket = new ServerSocket(8888);) {Socket socket = serverSocket.accept();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter pw = new PrintWriter(socket.getOutputStream());System.out.println("连接成功");while (true){String str = br.readLine();System.out.println("客户端说" + str);if ("exit".equals(str)){break;}pw.println(str);pw.flush();}} catch (IOException e) {System.out.println("服务器启动失败");throw new RuntimeException(e);}}
}
创建客户端
public class OneWaySocketClient {public static void main(String[] args) {try(Socket socket = new Socket("127.0.0.1",8888)) {Scanner scanner = new Scanner(System.in);PrintWriter pw = new PrintWriter(socket.getOutputStream());BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));while (true){String s = scanner.nextLine();pw.println(s);pw.flush();if ("exit".equals(s)){break;}String serverInput = br.readLine();System.out.println("服务器返回的" + serverInput);}}catch (Exception e){e.printStackTrace();}}
}
TCP双向通信
双向通信是指通信双方中,任何一方都可为发送端,任何一方都可为接收端
服务端
public class TwoWaySocketServer {public static void main(String[] args) {System.out.println("服务器启动,监听8888端口");try(ServerSocket serverSocket = new ServerSocket(8888);) {Socket socket = serverSocket.accept();//创建键盘输入对象Scanner scanner = new Scanner(System.in);BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter pw = new PrintWriter(socket.getOutputStream());while (true){String str = br.readLine();System.out.println("客户端说:" + str);String keyInput = scanner.nextLine();pw.println(keyInput);pw.flush();}}catch (Exception e){e.printStackTrace();}}
}
客户端
public class TwoWaySocketClient {public static void main(String[] args) {try(Socket socket = new Socket("127.0.0.1",8888)) {Scanner scanner = new Scanner(System.in);BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter pw = new PrintWriter(socket.getOutputStream());while (true){String keyInput = scanner.nextLine();pw.println(keyInput);pw.flush();String str = br.readLine();System.out.println("服务端说:" + str);}}catch (Exception e){e.printStackTrace();}}
}
创建点对点的聊天应用
创建服务端
主线程
public class ChatSocketServer {public static void main(String[] args) {try(ServerSocket serverSocket = new ServerSocket(8888)) {System.out.println("服务端启动,等待连接");Socket socket = serverSocket.accept();new Thread(new SendThread(socket)).start();new Thread(new ReceiveThread(socket)).start();}catch (Exception e){e.printStackTrace();}}
}
接收消息线程
public class ReceiveThread implements Runnable{private Socket socket;public ReceiveThread(Socket socket){this.socket = socket;}@Overridepublic void run() {this.receiveMsg();}private void receiveMsg(){try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));){while (true){String msg = br.readLine();System.out.println("客户端说:" + msg);}}catch (Exception e){e.printStackTrace();}}
}
发送消息线程
public class SendThread implements Runnable{private Socket socket;public SendThread(Socket socket){this.socket = socket;}@Overridepublic void run() {this.sendMsg();}private void sendMsg(){try(Scanner scanner = new Scanner(System.in);PrintWriter pw = new PrintWriter(socket.getOutputStream());){while (true){String msg = scanner.nextLine();pw.println(msg);pw.flush();}}catch (Exception e){e.printStackTrace();}}
}
创建客户端
主线程
public class ChatSocketClient {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1",8888);System.out.println("连接成功");new Thread(new ClientSendThread(socket)).start();new Thread(new ClientReceiveThread(socket)).start();}catch (Exception e){e.printStackTrace();}}
}
接收消息线程被
public class ClientReceiveThread implements Runnable{private Socket socket;public ClientReceiveThread(Socket socket){this.socket = socket;}@Overridepublic void run() {receiveMsg();}private void receiveMsg() {try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {while (true){String msg = br.readLine();System.out.println("服务端说:" + msg);}} catch (IOException e) {e.printStackTrace();}}
}
发送消息线程
public class ClientSendThread implements Runnable{private Socket socket;public ClientSendThread(Socket socket){this.socket = socket;}@Overridepublic void run() {this.sendMsg();}private void sendMsg() {try(Scanner scanner = new Scanner(System.in);PrintWriter pw = new PrintWriter(socket.getOutputStream())){while (true){String msg = scanner.nextLine();pw.println(msg);pw.flush();}}catch (Exception e){e.printStackTrace();}}
}
优化点对点的聊天应用
public class GoodTCP {public static void main(String[] args) throws IOException {ServerSocket serverSocket = null;Socket socket = null;try {Scanner scanner = new Scanner(System.in);System.out.println("请输入:server,<port> 获取 <ip>,<port>");String str = scanner.nextLine();String[] arr = str.split(",");if("server".equals(arr[0])){System.out.println("TCP Server Listen at" + arr[1] + "......");serverSocket = new ServerSocket(Integer.parseInt(arr[1]));socket = serverSocket.accept();new Receive(socket);}else {socket = new Socket(arr[0],Integer.parseInt(arr[1]));System.out.println("连接成功");}new Thread(new Send(socket, scanner)).start();new Thread(new Receive(socket)).start();}catch (Exception e){e.printStackTrace();}finally {if(serverSocket != null){serverSocket.close();}}}
}
public class Send implements Runnable{private Socket socket;private Scanner scanner;public Send(Socket socket, Scanner scanner) {this.socket = socket;this.scanner = scanner;}@Overridepublic void run() {this.sendMsg();}private void sendMsg(){try(PrintWriter pw = new PrintWriter(socket.getOutputStream());){while (true){String msg = scanner.nextLine();pw.println(msg);pw.flush();}}catch (Exception e){e.printStackTrace();}}
}
public class Receive implements Runnable{private Socket socket;public Receive(Socket socket){this.socket = socket;}@Overridepublic void run() {sendMsg();}private void sendMsg(){try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));){while (true){String msg = br.readLine();System.out.println("客户端说:" + msg);}}catch (Exception e){e.printStackTrace();}}
}
一对多应用
服务端应该将serverSocket.accept()放入while(true)循环中
一对多聊天服务器设计
难点在于解决线程同步
当没有消息发送时,发送线程处于等待状态,当接收线程接收到消息后,唤醒所有等待的发送线程
public class ChatRoomServer {public static String buf;public static void main(String[] args) {System.out.println("Chat Server Version 1.0");System.out.println("Listen at 8888......");try(ServerSocket serverSocket = new ServerSocket(8888)){while (true){Socket socket = serverSocket.accept();System.out.println("连接到" + socket.getInetAddress());new Thread(new ChatReceiveThread(socket)).start();new Thread(new ChatSendThread(socket)).start();}}catch (Exception e){e.printStackTrace();}}
}
public class ChatReceiveThread implements Runnable {private Socket socket;public ChatReceiveThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {receiveMsg();}private void receiveMsg() {try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));){while (true){String msg = br.readLine();synchronized ("abc"){ChatRoomServer.buf = "[" + this.socket.getInetAddress() + "]" + msg;"abc".notifyAll();}}}catch (Exception e){e.printStackTrace();}}
}
public class ChatSendThread implements Runnable{Socket socket;public ChatSendThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {sendMsg();}private void sendMsg() {try(PrintWriter pw = new PrintWriter(socket.getOutputStream());){while (true){synchronized ("abc"){//先让发送消息的线程处于等待状态"abc".wait();//将公共数据区的数据发送给客户端pw.println(ChatRoomServer.buf);pw.flush();}}}catch (Exception e){e.printStackTrace();}}
}
UDP通信实现原理
UDP协议与之前讲到的TCP协议不同,是面向无连接的,双方不需要建立连接便可通信。UDP通信所发送的数据需要进行封包操作(使用DatagramPacket类),然后才能接收或发送(使用DatagramSocket类)。
DatagramPacket:数据容器(封包)的作用
此类表示数据报包。 数据报包用来实现封包的功能。
常用方法
方法名 | 使用说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造数据报包,用来接收长度为 length 的数据包 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 |
getAddress() | 获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的 |
getData() | 获取发送或接收的数据 |
setData(byte[] buf) | 设置发送的数据 |
DatagramSocket:用于发送或接收数据报包
当服务器要向客户端发送数据时,需要在服务器端产生一个DatagramSocket对象,在客户端产生一个DatagramSocket对象。服务器端的DatagramSocket将DatagramPacket发送到网络上,然后被客户端的DatagramSocket接收。
DatagramSocket有两种常用的构造函数。一种是无需任何参数的,常用于客户端;另一种需要指定端口,常用于服务器端。如下所示:
- DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。
- DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。
常用方法
方法名 | 使用说明 |
---|---|
send(DatagramPacket p) | 从此套接字发送数据报包 |
receive(DatagramPacket p) | 从此套接字接收数据报包 |
close() | 关闭此数据报套接字 |
UDP通信编程基本步骤:
1、创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
2、创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
3、在服务器端定义DatagramPacket对象,封装待发送的数据包。
4、客户端将数据报包发送出去。
5、服务器端接收数据报包。
UDP通信入门案例
服务端
public class UDPServer {public static void main(String[] args) {//创建服务端接收数据的DatagramSocket对象try(DatagramSocket datagramSocket = new DatagramSocket(9999)){//创建数据缓冲区byte[] b = new byte[1024];//创建数据报包对象DatagramPacket datagramPacket = new DatagramPacket(b,b.length);//等待接收客户端所发送的数据datagramSocket.receive(datagramPacket);//取出数据String str = new String(datagramPacket.getData(),0,datagramPacket.getLength());System.out.println(str);}catch (Exception e){e.printStackTrace();}}
}
客户端
public class UDPClient {public static void main(String[] args) {try(DatagramSocket datagramSocket = new DatagramSocket(8888);) {byte[] bytes = "Triticale".getBytes();DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length,new InetSocketAddress("127.0.0.1",9999));datagramSocket.send(datagramPacket);}catch (Exception e){e.printStackTrace();}}
}
基本数据类型通信
服务端
try(DataInputStream dis = new DataInputStream(new ByteArrayInputStream(datagramPacket.getData()));){System.out.println(dis.readLong());
}
客户端
long n = 2000l;
try(ByteArrayOutputStream bos = new ByteArrayOutputStream();DataOutputStream dos = new DataOutputStream(bos);){dos.writeLong(n);byte[] arr = bos.toByteArray();DatagramPacket datagramPacket1 = new DatagramPacket(arr,arr.length,new InetSocketAddress("127.0.0.1",9999));
}
传递自定义数据类型
创建服务端
public class ObjectTypeUDPServer {public static void main(String[] args) {try(DatagramSocket datagramSocket = new DatagramSocket(9999)){byte[] bytes = new byte[1024];DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);datagramSocket.receive(datagramPacket);try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(datagramPacket.getData()))){Person person = (Person) ois.readObject();System.out.println(person.toString());}}catch (Exception e){e.printStackTrace();}}
}
创建客户端
public class ObjectTypeUDPClient {public static void main(String[] args) {try(DatagramSocket datagramSocket = new DatagramSocket(8888);ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos)){Person person = new Person();person.setName("张三");person.setAge(18);oos.writeObject(person);byte[] byteArray = bos.toByteArray();DatagramPacket datagramPacket = new DatagramPacket(byteArray,byteArray.length,new InetSocketAddress("127.0.0.1",9999));datagramSocket.send(datagramPacket);}catch (Exception e){e.printStackTrace();}}
}
相关文章:
【Java】网络编程(Socket)
网络编程 Socket 我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间,则使用套接字Socket来进行分离 套接字就像是传输层为应用层开的一个小口,应用程…...
力扣-226.翻转二叉树
题目描述 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 class Solution { public:TreeNode *invertTree(TreeNode *root) {if (!root) {return NULL;}TreeNode *temp root->right;root->right root->left;root->left …...
数据结构——例题1
eg1:求解 S 1! 2! 3! ... n! #include<stdio.h> #include<stdlib.h>long sum(int n){long s 0,t,i,j;for(i1;i<n;i){t1;for(j1;j<i;j){t*j;}st;}return s; }int main(){int n;printf("请输入一个整数:");scanf("…...
INT202 Complexity of Algroithms 算法的复杂度 Pt.7 NP-Completeness NP完全性
文章目录 1.P与NP问题1.1 计算上难以解决的问题(Hard Computational Problems)1.2 决策问题和优化问题(Decision/Optimization problems)1.3 计算问题的正式定义1.4 复杂性类1.4.1 复杂性类 P P P1.4.2 证明(Certifica…...
K8s 图形界面管理kubesphere
1. 概述 KubeSphere 是一个开源的、基于 Kubernetes 的容器平台,旨在简化企业级 Kubernetes 集群的部署、管理和运维。KubeSphere 提供了丰富的功能,包括多租户管理、DevOps 流水线、应用商店、监控与日志、服务网格、网络策略等,帮助企业快…...
MCU程序加密保护(一)闪存读写保护法 加密与解密
MCU(微控制器单元)的加密方法可以从硬件、软件和通信协议三个层面来理解。以下是常见的MCU加密手段,按类型分类说明: 针对目前 STM32 系列微控制器在程序加密保护方面手段单一、保护效果有限的问题,本文介绍并分析了四…...
Windows下安装mysql8.0
一、下载安装离线安装包 (下载过了,可以跳过) 下载网站:MySQL :: Download MySQL Installerhttps://dev.mysql.com/downloads/installer/ 二、安装mysql 三、安装完成验证...
ubuntu----100,常用命令2
目录 文件与目录管理系统信息与管理用户与权限管理网络配置与管理软件包管理打包与压缩系统服务与任务调度硬件信息查看系统操作高级工具开发相关其他实用命令 在 Ubuntu 系统中,掌握常用命令可以大幅提升操作效率。以下是一些常用的命令,涵盖了文件管理…...
PYTHON训练营DAY24
# SO代码我们的感情好像跳楼机 # 元组创建时,可以省略括号:my_tuple4 10, 20, thirty # 字符串要加“ ” 元组 一、创建 my_tuple1 (1, 2, 3) my_tuple2 (a, b, c) my_tuple3 (1, hello, 3.14, [4, 5]) # 可以包含不同类型的元素 print(my_tupl…...
Element UI 双击事件(@cell-dblclick 与 @row-dblclick)
Element UI 双击事件(cell-dblclick 与 row-dblclick) 一、核心双击事件绑定 表格单元格双击 事件绑定: 通过 cell-dblclick 监听单元格双击,接收四个参数(row, column, cell, event)。 示…...
云原生|kubernetes|kubernetes的etcd集群备份策略
简介: 云原生|kubernetes|kubernetes的etcd集群备份策略 前言: etcd作为集群的关键组件之一,还是非常有必要进行定期备份的,本例将会就如何更快更好的备份etcd以及应该有哪些策略做一解析。(二进制部署的etcd集群&…...
永不收费的软件,离线可用
上次在推荐PC端证件照软件时,有小伙伴问是否有安卓端的版本。当时我说有,只是需要测试一下再给大家推荐。 今天就为大家带来一款安卓端的证件照软件,有需要的小伙伴可以赶紧收藏起来! 底色证件照(安卓) 之…...
解锁课程编辑器之独特风姿
(一)强大的编辑功能 课程编辑器的编辑功能堪称一绝,就像是一位全能的艺术大师。在文字编辑方面,它提供了丰富的字体、字号选择,还能对文字进行加粗、倾斜、下划线等格式设置,让重点知识一目了然。比如教师…...
在企业级智能体浪潮中,商业数据分析之王SAS或将王者归来
继LLM大模型与GenAI生成式AI应用之后,智能体正在成为下一个风口。与基于LLM的GenAI应用不同,智能体将LLM的智能涌现能力与智能决策的能力相结合,让智能体不仅能够认知、分析和总结,还能够进行决策和执行决策,将知识与智…...
WPF自定义控件开发全指南:多内容切换与动画集成
WPF自定义控件开发全指南:多内容切换与动画集成 一、控件基础架构设计1.1 选择控件基类1.2 定义关键属性 二、动画系统集成2.1 淡入淡出动画实现2.2 滑动动画实现 三、视觉状态管理四、完整使用示例4.1 XAML声明4.2 动画触发逻辑 五、扩展与优化5.1 性能优化建议5.2…...
二维差分(主要看原数组与差分数组的关系)
#include<stdio.h> #include<windows.h> int main() { int n, m; scanf("%d%d", &n, &m); int d[n 2][n 2]; // 差分数组 int a[n 2][n 2]; // 原数组 // 初始化数组 for (int i 0; i < n 1; i) { for (int j 0; j < n 1; j) { d…...
AI+企业应用级PPT生成(实战)
使用DeepSeek生成PPT框架Kimi PPT助手生成PPT全流程教学 目录 工具简介操作步骤 2.1 DeepSeek生成PPT框架2.2 Kimi PPT助手生成PPT 案例演示注意事项与优化建议扩展应用场景 1. 工具简介 DeepSeek:国内领先的AI大模型,擅长生成结构化文本内容ÿ…...
EXCEL Python 实现绘制柱状线型组合图和树状图(包含数据透视表)
1、组合图、数据透视表 (1)数据预处理 知识点 日期函数 year() month()数据透视表操作 同比计算公式 环比计算公式 (2)excel 数据透视表插入组合图 a.2015~2017数据集处理方式: 操作: 结果 b.2020~20…...
OpenCV的CUDA模块进行图像处理
本文介绍了使用OpenCV和CUDA加速的四种图像处理技术:灰度化、高斯模糊、Sobel边缘检测和直方图均衡化。每种技术都通过将图像数据上传到GPU,利用CUDA进行加速处理,最后将结果下载回CPU。灰度化通过cv::cuda::cvtColor实现,高斯模糊…...
电路研究9.3.5——合宙Air780EP中的AT开发指南:MQTT 应用指南
应用概述 4G 模块支持 MQTT 和 MQTT SSl 协议, MQTT 应用的基本流程如下: 1、如果要支持 SSL ,配置 SSL 参数 2、通过 TCP 连接到 MQTT 服务器 3、发送 MQTT CONNECT 到服务器,打开会话连接 4、订阅或者发布消息…...
每日算法刷题计划Day5 5.13:leetcode数组3道题,用时1h
11. 26. 删除有序数组中的重复项(简单,双指针) 26. 删除有序数组中的重复项 - 力扣(LeetCode) 思想: 1.我的思想: 双指针遍历集合储存已有元素 2.官方思想: 题目条件有序数组删除重复元素,所以重复元素都是连续存在…...
常见排序算法及复杂度分析
冒泡排序 (Bubble Sort) 基本思想 相邻元素比较,大的元素后移 每轮将最大元素"冒泡"到末尾 代码实现 void bubbleSort(int arr[], int n) {for (int i 0; i < n-1; i) {for (int j 0; j < n-i-1; j) {if (arr[j] > arr[j1]) {swap(arr[j]…...
git 怎么更改本地的存储的密码
目录 找到控制面板---用户账户---凭证管理器 点击【windows凭据】,选择普通凭据,点击你要修改的地址。点击【编辑】 修改完,点击【保存】编辑 找到控制面板---用户账户---凭证管理器 点击【windows凭据】,选择普通凭据&#x…...
数据分析预备篇---Pandas的Series
Pandas优势 Pandas优势在于它是构建在NumPy之上的,继承了NumPy高性能的数组计算功能,同时还提供了更多复杂精细的数据处理功能(如缺失值处理、时间序列分析),支持表格型数据(DataFrame)和带标签的一维数据(Series) 安装Pandas Windows操作系统,在菜单栏搜索cmd,进入…...
Kaamel隐私合规洞察:Facebook美容定向广告事件分析
Kaamel隐私合规与数据安全团队分析报告 I. 引言:基于情绪的定向广告指控 A. 事件概述 近期,一则关于Meta(前身为Facebook)的指控引发了公众对数字隐私和广告伦理的广泛关注。该指控核心内容为,Meta公司涉嫌利用其平台…...
最优化方法Python计算:有约束优化应用——线性可分问题支持向量机
设问题的数据样本点 ( x i , y i ) (\boldsymbol{x}_i,y_i) (xi,yi), x i ∈ R n \boldsymbol{x}_i\in\text{R}^n xi∈Rn, y i 1 y_i\pm1 yi1, i 1 , 2 , ⋯ , m i1,2,\cdots,m i1,2,⋯,m。由于标签数据 y i ∈ { − 1 , 1 } y_i\…...
深入解析 I/O 模型:原理、区别与 Java 实践
一、I/O 模型的核心概念 I/O 操作的本质是数据在用户空间(应用程序内存)和内核空间(操作系统内核内存)之间的传输。根据数据准备与拷贝阶段的处理方式不同,I/O 模型可分为以下五类: 阻塞 I/O(…...
React系列——HOC高阶组件的封装与使用
技巧一:复用组件逻辑 具体而言,高阶组件是参数为组件,返回值为新组件的函数 const EnhancedComponent higherOrderComponent(WrappedComponent);For example: 参数复用 const withSize (Component) > {return class toSize extends C…...
72.编辑距离
编辑距离是指通过删除、插入和替换三种操作,将一个字符串转换为另一个字符串所需的最少操作次数。 首先定义状态:dp[i][j] 表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需的最少操作数。接下来定义状态转移方程: 如果 word1[i]…...
自适应稀疏核卷积网络:一种高效灵活的图像处理方案
自适应稀疏核卷积网络:一种高效灵活的图像处理方案 引言 在深度学习的大潮中,计算机视觉技术取得了长足的进步。其中,卷积神经网络(CNN)作为图像处理的核心工具,极大地推动了各类图像识别任务的效果提升。…...
c# UTC 时间赋值注意事项
文章目录 最佳实践:赋值时指定时区问题描述回答关键区别:DateTime.SpecifyKind 的作用1. 直接赋值 DateTime.UtcNow.Date2. 使用 DateTime.SpecifyKind 强制指定 最佳实践:赋值时指定时区 避免 C# 版本默认读取时采用 机器时区问题 如果需要UTC 时间…...
对端服务器重装系统之后远程SSH无法登录的问题
今天遇到一个SSH连接问题特此记录下。 我之前可以从本机使用SSH跳转到其他服务器,今天突然发现无法跳转了,有警告信息,此报错是由于远程的主机的公钥发生了变化导致的,可能是有异常,建议修改认证文件后再次登录。 突然…...
豌豆 760 收录泛滥现象深度解析与应对策略
xinruanj 一、收录泛滥现象的具体表现 当用户在豌豆760 中搜索某类应用时,往往会被数量庞大、功能相似的程序所包围。以图片编辑类应用为例,搜索结果中可能会出现数十款名称相近、图标相似的应用。这些应用不仅在界面设计上缺乏创新,甚至部…...
dockers笔记
docker 和 虚拟机的区别 虚拟机比较笨重,包括操作系统 虚拟化:将物理资源虚拟为逻辑资源 镜像 - 模板 容器 - 实例 docker hub - 分享 和 复用 容器化和dockerfile dockerfile实践 我们想打印一个js语句,如何构建镜像完成这个事情 新建了…...
Angular | 利用 `ChangeDetectorRef` 解决 Angular 动态显示输入框的聚焦问题
在 Angular 应用开发中,实现用户点击按钮后,原地切换显示一个输入框并自动获取焦点的功能,是一个常见的交互模式。例如,搜索图标点击后变为搜索框,用户可以直接输入。然而,由于 Angular 的变更检测和 DOM 更…...
Redis——数据结构
Redis的五种基本数据类型:String、Hash、List、Set、ZSet 结构类型结构存储值结构读写能力String字符串、整数或浮点数对整个字符串或字符串的一部分进行操作;对整数或者浮点数进行自增或自减操作List链表,每个节点上包含一个字符串对链表两…...
通讯录管理系统(IO_序列化和反序列化版)
参照之前文章,也是IO的变版 package day4;import java.io.Serializable;/* 有需求 -- 才去设计类 自定义表示通讯录单条信息的类*/ public class PhoneBookItem implements Serializable {private static final long serialVersionUID 1L;//属性private String na…...
基于RT-Thread的STM32F4开发第三讲——DAC
文章目录 前言一、DAC是什么?二、RT-Thread工程创建三、DAC函数编写1.DAC.c2.DAC.h3.main.c 四、结果测试五、工程分享 前言 本章利用RT-Thread最新的驱动5.1.0开发DAC模块,使用的开发板是正点原子的STM32F4探索者。很多配置和上文重复,本文…...
git cherry-pick和git stash命令详解
git cherry-pick命令 定义 用于将指定的提交(commit)从一个分支"挑选"并应用到当前分支它复制某个提交的更改(diff),生成一个新的提交,保留原提交的更改内容,但拥有新的提交ID(SHA值)…...
MapReduce基本介绍
核心思想 分而治之:将大规模的数据处理任务分解成多个可以并行处理的子任务,然后将这些子任务分配到不同的计算节点上进行处理,最后将各个子任务的处理结果合并起来,得到最终的结果。 工作流程 Map 阶段: 输入数据被…...
正则表达式常用验证(一)
正则表达式(Regular Expression)是一种强大的文本匹配工具,常用于验证字符串的格式。以下是常见的正则表达式验证场景及其对应的表达式: 1. 数字验证 验证纯数字: ^\d+$示例:123、456789 验证固定长度的数字(如 6 位): ^\d{6}$示例:123456 验证数字范围(如 1 到 100…...
基于几何布朗运动的股价预测模型构建与分析
基于几何布朗运动的股价预测模型构建与分析 摘要 本文建立基于几何布朗运动的股价预测模型,结合极大似然估计与蒙特卡洛模拟,推导股价条件概率密度函数并构建动态预测区间。实证分析显示模型在标普500指数预测中取得89%的覆盖概率,波动率估…...
通过SSRF击穿内网!kali-ssrf靶场实战!
目录 1. 靶场拓扑图 2. 判断SSRF的存在 3. SSRF获取本地信息 3.1. SSRF常用协议 3.2. 使用file协议 4. 172.150.23.1/24探测端口 5. 172.150.23.22 - 代码注入 6. 172.150.23.23 SQL注入 7. 172.150.23.24 命令执行 7.1. 实验步骤 8. 172.150.23.27:6379 Redis未授权…...
Yarn-概述
一、YARN 是什么? YARN(Yet Another Resource Negotiator) 是 Apache Hadoop 生态系统中的核心组件,是一个 分布式资源管理和作业调度系统,主要用于协调集群中的计算资源(CPU、内存、磁盘、网络等…...
如何在sheel中运行spark
// 读取文件,得到RDD val rdd1 sc.textFile("hdfs://hadoop100:8020/wcinput/words.txt") // 将单词进行切割,得到一个存储全部单词的RDD val rdd2 fileRDD.flatMap(line > line.split(" ")) // 将单词转换为元组对象࿰…...
销售具备的能力有哪些
销售人员是许多公司业务的开拓者,他们的存在让公司的利益更高。因此,在许多的公司中,销售人员的待遇都非常的高。也因此,有的人看重销售人员的薪资待遇想寻找销售型的工作。但是,相当销售人员还需要具有一定的工作能力…...
React面试常问问题详解
以下是30个React面试中常见的问题及简要解析,涵盖基础概念、核心原理、性能优化、Hooks、状态管理等方面,适用于初中高级开发者准备面试时参考: 一、React 基础与核心概念 React 是什么? React 是由 Facebook 开发的用于构建用户界…...
POM 和关键字驱动区别
一、POM 和关键字驱动的区别以及各自的优势分别是什么? 1、POM 适用于对单个系统封装的自动化框架中,对业务覆盖更精准; 优势:更加便利、维护性更高 2、关键字驱动可以用于对多个业务、多个系统进行封装的自动化框架中&…...
2025年PMP 学习十一 第8章 项目质量管理(8.3)
第8章 项目质量管理(8.3) 文章目录 第8章 项目质量管理(8.3)8.3 控制质量1. 定义与作用2.输入、输出,工具和技术3. 数据收集 - 核查表(工具与技术)4. 数据展示 - 帕雷托图(工具与技术…...
【笔记】C++操作mysql及相关配置
目录 使用软件版本信息: 1. C配置mysql相关依赖 1.1 下载 1.2 文件配置 1.3 C编译器配置 2、测试程序 使用软件版本信息: Visual Studio 2022Mysql 8.0C Connector库 8.3.0 可直接在https://download.csdn.net/download/Word_And_Me_/90826524下…...