【Java】网络编程(Socket)

news2025/7/16 13:36:15

网络编程

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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }

    @Override
    public 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;
    }
    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

思科(Cisco ASA/Firepower)、华三(H3C)、华为(Huawei USG)防火墙 的基础配置

以下是针对 思科&#xff08;Cisco ASA/Firepower&#xff09;、华三&#xff08;H3C&#xff09;、华为&#xff08;Huawei USG&#xff09;防火墙 的基础配置指南&#xff0c;涵盖 区域划分、安全策略、NAT、路由 等核心功能。配置示例基于通用场景&#xff0c;实际部署时需根…

Windows环境下maven的安装与配置

1.检查JAVA_HOME环境变量 Maven是使用java开发的&#xff0c;所以必须知道当前系统环境中的JDK的安装目录。 搜索栏直接输入“cmd” 或者 WinR 输入cmd 在打开的终端窗口输入“echo %JAVA_HOME”&#xff0c;就可以看到jdk的位置了。 如果没有的话&#xff0c;请参考我的文章&a…

LeetCode:513、找树左下角的值

//递归法 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* t…

Vxe UI vue vxe-table 实现表格数据分组功能,不是使用树结构,直接数据分组

Vxe UI vue vxe-table 实现表格数据分组功能&#xff0c;不是使用树结构&#xff0c;直接数据分组 查看官网&#xff1a;https://vxetable.cn gitbub&#xff1a;https://github.com/x-extends/vxe-table gitee&#xff1a;https://gitee.com/x-extends/vxe-table 代码 通过…

如何禁止chrome自动更新

百度了一下 下面这个方法实测有效 目录 1、WINR 输入 services.msc 2、在Services弹窗中找到下面两个service并disable 3、验证是否禁止更新成功&#xff1a; 1、WINR 输入 services.msc 2、在Services弹窗中找到下面两个service并disable GoogleUpdater InternalService…

阳光学院【2020下】计算机网络原理-A卷-试卷-期末考试试卷

一、单选题&#xff08;共25分&#xff0c;每空1分&#xff09; 1.ICMP协议工作在TCP/IP参考模型的 ( ) A.主机-网络 B.网络互联层 C.传输层 D.应用层 2.下列关于交换技术的说法中&#xff0c;错误的是 ( ) A.电路交换适用于突发式通信 B.报文交换不能满足实时通信 C.报文…

kotlin-协程(什么是一个协程)

1.什么指一个协程对于线程来说一个thread就是就是指一个线程&#xff0c;thread为什么成为线程呢&#xff1f;因为他实现了对线程的一个抽象管理&#xff0c;可以管理这个线程&#xff0c;启动&#xff0c;可以查看各种信息 那么协程呢&#xff1f; public fun CoroutineScop…

数组和切片的区别

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

WPF内嵌其他进程的窗口

WPF内嵌其他进程窗口的常见方法有 HwndHost SetParent 和 WindowsFormsHost WinForms Panel SetParent 推荐使用自定义HwndHost 两者的对比区别 示例代码 public class MyWndHost : HwndHost {const int WS_CHILD 0x40000000;const int WS_VISIBLE 0x10000000;const i…

CVPR2025 | Prompt-CAM: 让视觉 Transformer 可解释以进行细粒度分析

Prompt-CAM: Making Vision Transformers Interpretable for Fine-Grained Analysis 摘要-Abstract引言-Introduction方法-Approach预备知识-PreliminariesPrompt-CAM: Prompt Class Attention Map特征识别与定位-Trait Identification and Localization变体与扩展-Variants an…

解锁 DevOps 新境界 :使用 Flux 进行 GitOps 现场演示 – 自动化您的 Kubernetes 部署

前言 GitOps 是实现持续部署的云原生方式。它的名字来源于标准且占主导地位的版本控制系统 Git。GitOps 的 Git 在某种程度上类似于 Kubernetes 的 etcd&#xff0c;但更进一步&#xff0c;因为 etcd 本身不保存版本历史记录。毋庸置疑&#xff0c;任何源代码管理服务&#xf…

LLM大模型中的基础数学工具—— 信号处理与傅里叶分析

Q51: 推导傅里叶变换 的 Parseval 定理 傅里叶变换的 Parseval 定理揭示了啥关系&#xff1f; Parseval 定理揭示了傅里叶变换中时域与频域的能量守恒关系&#xff0c;即信号在时域的总能量等于其在频域的总能量。这就好比一个物体无论从哪个角度称重&#xff0c;重量始终不…

橡胶制品行业质检管理的痛点 质检LIMS如何重构橡胶制品质检价值链

橡胶制品广泛应用于汽车、医疗、航空等领域&#xff0c;其性能稳定性直接关联终端产品的安全性。从轮胎耐磨性测试到密封件耐腐蚀性验证&#xff0c;每一项检测数据都是企业参与市场竞争的核心筹码。然而&#xff0c;传统实验室管理模式普遍面临设备调度混乱、检测流程追溯断层…

CAElinux系统详解

CAElinux 系统详解&#xff1a;从系统层面到专业应用 一、CAElinux 的定位与核心目标 CAElinux 是一款专门为 计算机辅助工程&#xff08;CAE&#xff09; 设计的定制化 Linux 发行版&#xff0c;目标用户为从事工程仿真、数值模拟、高性能计算&#xff08;HPC&#xff09;的…

计算机系统----软考中级软件设计师(自用学习笔记)

目录 1、计算机的基本硬件系统 2、CPU的功能 3、运算器的组成 4、控制器 5、计算机的基本单位 6、进制转换问题 7、原码、反码、补码、移码 8、浮点数 9、寻址方式 10、奇偶校验码 11、海明码 12、循环冗余校验码 13、RISC和CISC 14、指令的处理方式 15、存储器…

django的权限角色管理(RBAC)

在 Django 中&#xff0c;User、Group 和 Permission 是权限系统的核心组件。下面通过代码示例演示它们的 CRUD&#xff08;创建、读取、更新、删除&#xff09; 操作&#xff1a; 一、User 模型 CRUD from django.contrib.auth.models import User# 创建用户 user User.obje…

线性表-顺序表(Sequential List)

1 线性表 1.1 顺序表&#xff08;Sequential List&#xff09; 顺序表并不难理解&#xff0c;主要是知道顺序表是在内存中连续存储的一段数据&#xff0c;知道这个后&#xff0c;相应的算法也就非常简单了。 线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的…

【阿里云免费领取域名以及ssl证书,通过Nginx反向代理web服务】

文章目录 前言一、申请域名1.1 访问阿里云官网1.2 输入自定义域名1.3 创建个人模板1.4 支付1元可以使用域名1年1.5 按照提示实名认证1.6 实名认证成功 二、域名解析2.1 选择域名解析2.2 解析设置2.3 快速添加解析2.4 选择对应类型2.5 解析成功 三、申请免费ssl证书3.1 访问阿里…

数据分析2

五、文件 CSV Comma-Separated Value&#xff0c;逗号分割值。CSV文件以纯文本形式存储表格数据&#xff08;数字和文本&#xff09;。 CSV记录间以某种换行符分隔&#xff0c;每条记录由字段组成&#xff0c;字段间以其他字符或字符串分割&#xff0c;最常用逗号或制表符。…

实战项目5(08)

目录 任务场景一 【r1配置】 【r2配置】 【r3配置】 ​​​​​​​任务场景二 【r1配置】 【r2配置】 ​​​​​​​任务场景一 按照下图完成网络拓扑搭建和配置 任务要求&#xff1a; 通过在路由器R1、R2和R3上配置静态路由&#xff0c;实现网络中各终端PC能够正常…