• 《网络编程从入门到入魔》(建议收藏)


    网络编程

    1.1、 概述


    计算机网络
    		是指将地理位置不同的具有独立功能的多台计算机及其外部设备,
    		通过通信线路连接起来,
    		在网络操作系统,网络管理软件及网络通信协议的管理和协调下,
    		实现资源共享和信息传递的计算机系统。
    
    网络编程
    		就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.2、网络通讯的要素


    规则:网络通信协议

    OSI中的层

    功能

    TCP/IP协议

    应用层

    文件传输,电子邮件,文件服务,虚拟终端

    TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet

    表示层

    数据格式化,代码转换,数据加密

    没有协议

    会话层

    解除或建立与别的接点的联系

    没有协议

    传输层

    提供端对端的接口

    TCP、UDP

    网络层

    为数据包选择路由

    IP,ICMP,RIP,OSPF,BGP,IGMP

    数据链路层

    传输有地址的帧以及错误检测功能

    SLIP,CSLIP,PPP,ARP,RARP,MTU

    物理层

    以二进制数据形式在物理媒体上传输数据

    ISO2110,IEEE802。IEEE802.2

    • P和端口号

    • 网络通讯协议(UDP,TCP)

    1.3、IP

    ip地址:InetAddress

    • 唯一定位一台网络计算机

    • 127.0.0.1:本机localhost

    • IP地址的分类

      ip地址分类(ipv/ipv6)

      • ==ipv4:==127.0.0.1,四个字节组成,长度为0-255,42亿
      • ==ipv6:==如(2020:0bb2:aaaa:0256:0000:0000:da59:3684),128位,无符号整数!

      公网(互联网)私网(局域网)分类

      • ABDC类地址

      • 192.168.xx.xx:专门给组织机构使用的

    • 域名:记忆IP问题!

    代码示例:

    import java.net.InetAddress;
    
    //测试IP
    public class TestInetAddress {
        public static void main(String[] args) {
            try {
                //查询本机地址
                InetAddress  InetAddress1 = InetAddress.getByName("127.0.0.1");
                System.out.println( InetAddress1);
                InetAddress  InetAddress3 = InetAddress.getByName("localhost");
                System.out.println( InetAddress3);
                InetAddress  InetAddress4 = InetAddress.getLocalHost();
                System.out.println( InetAddress4);
    
                //查询网站ip地址
                InetAddress  InetAddress2 = InetAddress.getByName("www.baidu.com");
                System.out.println( InetAddress2);
    
    
                //常用方法
                System.out.println(InetAddress2.getAddress());
                System.out.println(InetAddress2.getCanonicalHostName());//规范的名字
                System.out.println(InetAddress2.getHostAddress());//ip
                System.out.println(InetAddress2.getHostName());//域名,或者本机电脑的名字
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    1.4、端口


    端口表示计算机上的一个程序的进程

    • 不同的进程有不同的端口号!用来区分软件!

    • 被规定0-65535

    • 分为TCP:UDP

    • 端口分类

      • 公用端口 0-1023

        • HTTP:80
        • HTTPS:443
        • FTP:21
        • Telent:23
      • 程序注册端口:1024-49151,分配给用户或者程序

        • Tomca:8080
        • MySQL:3306
        • Oracle:1521
      • 动态、私有端口:49152-65535

      netstat -ano:查看所有端口

      netstat -ano | findstr “本机端口号”:查看指定的端口

      tastlist | findstr “指定查询的端口号”:查看指定端口的进程

      代码示例:

      package Demo01;
      
      import java.net.InetAddress;
      import java.net.InetSocketAddress;
      
      public class TestInetSocketAddress {
          public static void main(String[] args) {
              InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8080);
              InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);
              System.out.println(socketAddress);
              System.out.println(socketAddress2);
      
              System.out.println(socketAddress.getAddress());
              System.out.println(socketAddress.getHostName());//地址
              System.out.println(socketAddress.getPort());//端口
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    1.5、通信协议


    • 网络通信协议:涉及到速率,传输码率,代码结构,传输控制…

    • TCP/IP协议簇(实际上是一组协议)

      • TCP协议:用户传输协议
      • UDP协议:用户数据报协议
    • TCP/UDP对比:

      • TCP:拨电话

        • 连接、稳定

        • “三次握手”、”四次分手“

        •   最少需要三次,保证连接稳定
            A:你愁啥?
            B:瞅你咋地!
            A:干一场!
            
            A:我要走了
            B:我知道你要走了
            B:你真的要走了吗?
            A:我真的要走了.
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
        • 客户端、服务端

        • 传输完成后,释放连接,效率低

      • UDP:发短信

        • 不连接、不稳定

        • 客户端、服务端(没有明确的界限)

        • 随时随地都可以发送

        • DDOS:供水攻击!(饱和攻击)

    1.6、TCP

    • 客户端

      1.连接服务器 Socket

      2.发送消息

    • 服务器

      1.建立服务端口 ServerSockte

      2.等待用户的连接 accpt

      3.接收用户的消息

    客户端代码示例:

    package Demo02;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.InterfaceAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    //客户端
    public class TcpClientDemo01 {
        public static void main(String[] args) {
            Socket socket =null;
            OutputStream os=null;
            try {
                //1.要知道服务器的地址、端口号
                InetAddress serviceIP= InetAddress.getByName("127.0.0.1");
                int port=9999;
                //2.创建一个socket连接
                socket = new Socket(serviceIP, port);
                //3.发送消息  I/O流
                os = socket.getOutputStream();
    
                os.write("你好,欢迎学习Java".getBytes());
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(os!=null)
                {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
            }
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    服务端代码示例:

    package Demo02;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    //服务端
    public class TcpServerDemo01 {
        public static void main(String[] args) {
            ServerSocket serverSocket=null;
            Socket socket =null;
            InputStream is =null;
            ByteArrayOutputStream  baos =null;
            try {
                //1.需要有一个地址
               serverSocket = new ServerSocket(9999);
               while(true){
                   //2.等待客户端连接过来
                   socket = serverSocket.accept();
                   //3.读取客户端的消息
                   is = socket.getInputStream();
                   //管道流
                   baos = new ByteArrayOutputStream();
                   byte[] buffer = new byte[1024];
                   int len;
                   while((len=is.read(buffer))!=-1){
                       baos.write(buffer,0,len);
                   }
                   System.out.println(baos.toString());
               }
    
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //关闭资源
                if(baos!=null){
                    try {
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
              if( is!=null){
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if(socket!=null){
                  try {
                      socket.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if( serverSocket!=null){
                  try {
                      serverSocket.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
               }
    
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    文件上传

    客户端代码示例:

    package Demo02;
    
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    //客户端
    public class TcpClientDemo02 {
        public static void main(String[] args) throws Exception {
            //1.创建一个Socket连接
            Socket socket=new Socket(InetAddress.getByName("127.0.0.1"),9000);
    
            //2.创建一个输出流
            OutputStream os=socket.getOutputStream();
    
    
            //3.读取文件
            FileInputStream fis=new FileInputStream(new File("tx.png"));
    
            //4.写入文件
            byte[] buffer=new byte[1024];
            int len;
            while ((len=fis.read(buffer))!=-1){
                os.write(buffer,0,len);
            }
    
    
    
            //通知服务器,我已经结束了
            socket.shutdownOutput();  //我已经传输完了!
    
            //确定服务端接收完毕,才能够断开连接
            InputStream inputStream=socket.getInputStream();
            //String byte[]
            ByteArrayOutputStream baos=new ByteArrayOutputStream();
            byte[] buffer2=new byte[2014];
            int len2;
            while ((len2=inputStream.read(buffer2))!=-1){
                baos.write(buffer2,0,len2);
            }
            System.out.println(baos.toString());
    
    
            //5.关闭资源
            baos.close();
            inputStream.close();
            fis.close();
            os.close();
            socket.close();
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    服务端代码示例:

    package Demo02;
    
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    //服务端
    public class TcpServerDemo02 {
        public static void main(String[] args) throws IOException {
            //1.创建服务
            ServerSocket serverSocket=new ServerSocket(9000);
            //2.监听客户端的连接
            Socket socket=serverSocket.accept();//阻塞式监听,会一直等待客户端连接
            //3.获取输入流
            InputStream is=socket.getInputStream();
            //4.文件输出
            FileOutputStream fos=new FileOutputStream(new File("receive.png"));
            byte[] buffer=new byte[1024];
            int len;
            while ((len=is.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
    
    
            //通知客户端接收完毕了
            OutputStream os = socket.getOutputStream();
            os.write("我接收完毕了,你可以断开了".getBytes());
    
            //5.关闭资源
            fos.close();
            is.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    Tomcat

    • 服务端
      • 自定义 S
      • Tomcat服务器 S:Java后台开发!
    • 客户端
      • 自定义 S
      • 浏览器 B

    1.7、UDP


    发短信:不用连接,但是需要对方的地址

    发送消息代码示例:
    package Demo03;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    //不要连接服务器
    public class UdpClientDemo01 {
        public static void main(String[] args) throws Exception {
            //1.建立一个Socket
            DatagramSocket socket = new DatagramSocket();
    
            //2.建个 包
            String msg="你好啊,服务器!";
    
            //接收对象
            InetAddress localhost = InetAddress.getByName("localhost");
            int port=9090;
            //以下解释:数据、数据长度起始、接收对象
            DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
    
            //3.发送 包
            socket.send(packet);
    
            //4.关闭流(资源)
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    接收端代码示例:

    package Demo03;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    //这边也是需要等待客户端的连接
    public class UdpServerDemo01 {
        public static void main(String[] args) throws Exception {
            //1.开放端口
            DatagramSocket socket = new DatagramSocket(9090);
    
            //2.接收数据(即接收包)
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收
            //这里将  DatagramPacket封装  成一个对象
    
            socket.receive(packet); //阻塞接收
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(new String(packet.getData(),0,packet.getLength()));
    
            //3.关闭连接
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    UDP聊天实现(咨询)

    循环发送消息

    发送端代码示例:

    package Char;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    
    public class UdpSenderDemo01 {
        public static void main(String[] args) throws Exception {
            DatagramSocket socket= new DatagramSocket(8888);
    
            //准备数据:控制台读取 System.in
            BufferedReader reader=   new BufferedReader(new InputStreamReader(System.in));
            while (true){
                String data= reader.readLine();
                byte[] datas=data.getBytes();
                DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
                socket.send(packet);
                if (data.equals("bye")){
                    break;
                }
            }
             socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    接收端代码示例:

    package Char;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    public class UdpReceiveDemo01 {
        public static void main(String[] args) throws Exception {
            DatagramSocket socket = new DatagramSocket(6666);
    
            while (true){
                //准备接收包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container,0,container.length);
                socket.receive(packet);//阻塞式接收包裹
                //断开连接
                byte[] data=packet.getData();
                String receiveData = new String(data, 0, data.length);
                System.out.println(receiveData);
    
                if(receiveData.equals("bye")) {
                    break;
                }
            }
            socket.close();
    
    
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在线咨询:两个人都可以是发送方,也都可以是接收方!

    发送端:

    package Char;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    
    public class TalkSend implements Runnable{
        DatagramSocket socket=null;
        BufferedReader reader=null;
        private int  fromPort;
        private  String toIP;
        private  int toPort;
        //alt+insert创建构造器
        public TalkSend(int fromPort, String toIP, int toPort) {
            this.fromPort = fromPort;
            this.toIP = toIP;
            this.toPort = toPort;
            try {
                 socket = new DatagramSocket(fromPort);
                 reader= new BufferedReader(new InputStreamReader(System.in));  //准备数据:控制台读取 System.in
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            //run负责发送消息
            while (true){
                try{
                    String data= reader.readLine();
                    byte[] datas=data.getBytes();
                    DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));
                    socket.send(packet);
                    if (data.equals("bye")){
                        break;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    接收端:

    package Char;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class TalkReceive implements  Runnable{
        DatagramSocket socket=null;
        private int port;
        private  String msgFrom;
    
        public TalkReceive(int port, String msgFrom) {
            this.port = port;
            this.msgFrom=msgFrom;
            try {
               socket= new DatagramSocket(port);
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            while (true) {
                try {
                    //准备接收包裹
                    byte[] container = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                    socket.receive(packet);//阻塞式接收包裹
                    //断开连接
                    byte[] data = packet.getData();
                    String receiveData = new String(data, 0, data.length);
                    System.out.println(msgFrom + ":" + receiveData);
    
                    if (receiveData.equals("bye")) {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    学生端:

    package Char;
    
    public class TalkStudent {
        public static void main(String[] args) {
            //1.开启两个线程
            new Thread(new TalkSend(7777,"localhost",9999)).start();
            //从(来自,自己的端口)7777端口发出去、发给本地localhost这个人,发送到9999端口
            new Thread(new TalkReceive(8888,"老师")).start();
            //接收8888端口的消息,来自老师的消息
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    老师端:

    package Char;
    
    public class TalkTeacher {
        public static void main(String[] args) {
            new Thread(new TalkSend(5555,"localhost",8888)).start();
            //从(来自,自己的端口)5555端口,发给本地localhost这个人,发送到8888端口
            new Thread(new TalkReceive(9999,"学生")).start();
            //接收9999端口的消息,来自学生的消息
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    1.8 URL

    https://www.baidu.com/

    统一资源定位符:定位资源的额,定位互联网的资源

    DNS域名解析 www.baidu.com xxx.xxx.xxx


    • 协议://ip地址:端口号/项目名/资源

    代码示例:

    package Demo04;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class UrlDown {
        public static void main(String[] args) throws Exception {
            //1.下载地址
            URL url = new URL("http://localhost:8080/docs/BUILDING.txt");
            //2.连接到这个资源 用HTTP连接
            HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
    
            InputStream inputStream = urlConnection.getInputStream();
    
            FileOutputStream fos= new FileOutputStream("BUILDING.txt");
            byte[] buffer = new byte[1024];
            int len;
            while ((len=inputStream.read(buffer))!=-1){
                fos.write(buffer,0,len); //写出这个数据
            }
            fos.close();
            inputStream.close();
            urlConnection.disconnect();//断开连接
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    数据结构系列学习(五) - 双向链表(Double_Linked_List)
    神马搜索引擎
    不下载软件,可以把电脑本地文件快速传到远端服务器里吗?
    PM2管理器无法使用解决方法
    反序列化漏洞详解
    网页脚本语言第一节课9.19
    【IEEE独立出版】第四届计算机科学与区块链国际学术会议 (CCSB 2024)
    centos7 mysql5.7离线安装
    将小程序容器技术应用到物联网IoT生态建设中
    salesforce零基础学习(一百二十)快去迁移你的代码中的 Alert / Confirm 以及 Prompt吧
  • 原文地址:https://blog.csdn.net/m0_67401606/article/details/126553102