【JAVA CORE_API】Day18 网络编程、线程、在线聊天室v1.0

news2024/11/28 18:45:39

C/S:客户端/服务器端,所有网络应用都是基于客户端服务器端进行的,Java写的是服务端,客户端是一个软件,服务端也是一个软件,两个软件之间交互;(只能连接对应的服务器)

B/S:浏览器/服务器端,它本质上也是C/S,只不过它的C是一个浏览器而已;(连接任意服务器都可以、百度、淘宝、京东等)

聊天室:两个程序A和B,一个是客户端、一个是服务端:谁发起连接,谁是客户端;谁接收连接,谁是服务端。

想连在一起需要网络,目的是为了传输数据,发送数据的过程中时需要遵守一些协议的:
TCP协议:可靠传输协议,发送数据后需要对方确认,对方确认后才能继续发送数据,再需要对方确认,100%所有数据发送过去,比较像打电话,需要接电话才能听见。虽然说数据完全可靠,但效率低下;
UDP:不可靠传输协议,只管发,不管对方能否接收到,有点像大广播,播了就播了,不管你听没听见。虽然不能保证数据100%都发送成功,但是效率比较高。

但是我们学习的时候学TCP,因为日后面对的客户端都是B(浏览器),而浏览器和客户端之间采用的协议是Http协议,Http协议要求地下客户端服务端传输时必须建立在可靠传输协议TCP上。

网络编程

什么是Socket编程

什么是Socket编程

  • java.net.SocketJava提供的用于进行网络编程的API;

  • Socket编程可以让软件与软件之间以计算机作为载体,以网络作为信息流动的通道进行远端数据传递,达到交流的目的。

什么是计算机网络

  • 计算机网络是指将具有独立功能的多台计算机通过通信线路连接起来,实现数据共享和交流的计算机系统。

什么是Socket

  • Socket(套接字):网络通信的标准API、进行可靠的网络通讯。

Socket通讯

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

IP地址(楼)

在这里插入图片描述

端口(门)

在这里插入图片描述

IP+端口

在这里插入图片描述

客户端与服务端(C/S)

在这里插入图片描述

Socket通讯

在这里插入图片描述

在这里插入图片描述

ServerSocket

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

多客户端支持

如何接受多客户端

  • ServerSocket提供方法:

    • Socket accept():用于监听服务端口,一旦一个客户端连接即返回一个Socket

    • 多次调用该方法可以感知多个客户端的连接。

在这里插入图片描述

建立连接

建立连接

  • Server.java

     package socket;
     import java.io.IOException;
     import java.net.ServerSocket;
     import java.net.Socket;
     
     /**
      * 服务端
      */
     public class Server {
         /**
          * java.net.ServerSocket:
          * 运行在服务端,主要作用两个:
          * 1.向系统申请服务端口,客户端通过该端口与服务端建立连接
          * 2.监听服务端口,一旦有客户端连接了,就会立即创建一个Socket对象与客户端进行交互
          *   如果将Socket比喻为"电话",那ServerSocket就相当于客户中心的"总机"
          */
         private ServerSocket serverSocket;
         public Server(){
             try {
                 System.out.println("正在启动服务器");
                 /**
                  * 创建ServerSocket对象时,会申请一个端口
                  * 如果该端口被其它程序占用,会抛出异常:
                  *   java.net.BindException: Address already in use:
                  * 解决办法:
                  * 1.更换端口号
                  * 2.杀死占用该端口的进行(通常由于服务端启动两次导致)
                  */
                 serverSocket = new ServerSocket(8088);
                 System.out.println("服务器启动完毕");
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     
         /**
          * 该方法用于启动程序的执行
          */
         public void start(){
             try {
                 System.out.println("等待客户端连接...");
                 /*
                  accept():
                  用于接收客户端连接,并返回一个Scoket对象与所连接的客户端进行交互
                  该方法是一个阻塞方法,调用后程序会"卡住",直接一个客户端连接为止
                  */
                 Socket socket = serverSocket.accept();
                 System.out.println("一个客户端连接了!");
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     
         public static void main(String[] args) {
             Server server = new Server();
             server.start();
         }
     }
    
  • Client.java

    package socket;
    import java.io.IOException;
    import java.net.Socket;
    /**
     * 客户端
     */
    public class Client {
        /*
          java.net.Socket:套接字
          它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互
         */
        private Socket socket;
        public Client(){
            try {
                System.out.println("正在连接服务端...");
                /*
                 实例化Socket对象,就是与远端计算机建立连接的过程
                 需要传入两个对数:
                 1.服务端的IP地址,用于找到网络上对方的计算机
                 2.服务端口,用于找到服务端计算机上的应用程序
    
                 查看IP操作:
                  Windows: win+r,输入cmd,回车,输入ipconfig,IPv4就是IP地址
                  Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址
                 */
                socket = new Socket("localhost",8088);
                System.out.println("服务端连接成功!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 该方法用于启动客户端程序的执行
         */
        public void start(){
    
        }
    
        public static void main(String[] args) {
            Client client = new Client();
            client.start();
        }
    }
    
  • 注意在尝试连接本地时要提前打开服务端Server.java,再连接自己,之后就可以通过其他人给出的端口号及IP地址连接其他人。

客户端发送文本数据

  • 利用IO只是中的流连接,使用客户端的Socket获取输出流进行流连接,利用PrintWriter来实现发送一行字符串的操作。

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

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

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

Server.java

package day18;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * 服务端
 */
public class Server {
    /**
     * java.net.ServerSocket:
     * 运行在服务端,主要作用有两个:
     * 1.像系统申请服务端口,客户端通过该端口与服务端建立连接
     * 2.监听服务端口,一旦有客户链接了,就会立即创建一个Socket对象与客户端进行交互
     *      如果将Socket比喻为“电话”,那ServerSocket就相当于客户中心的“总机”。
     * 解决方法:
     * 1.更换端口号;
     * 2.杀死占用该端口的进行(通常由于服务端启动了两次导致)
     */
    private ServerSocket serverSocket;
    public Server(){
        try {
            System.out.println("正在启动服务端......");
            serverSocket = new ServerSocket(8888);
            System.out.println("服务端启动完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 启动服务端方法:
    public void start(){
        try {
            while (true){
                System.out.println("服务端正在等待客户端连接......");
                /**
                 * accept():
                 * 用于接收客户端连接,并返回一个Socket对象与所连接的客户端进行交互
                 * 该方法是一个阻塞方法,调用后程序会“卡住”,直到一个客户端连接为止
                 */
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端连接了!");
                // 接收客户端发送过来的消息
                InputStream inputStream = socket.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String message;
                while ((message = bufferedReader.readLine()) != null) {    // 读取客户端发送过来的消息
                    System.out.println("客户端说:" + message);
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }

}

Client.java

package day18;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 客户端
 */
public class Client {
    /**
     * java.net.Socket:套接字
     * 它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互
     * 可以理解为是电话
     */
    private Socket socket;
    public Client() {
        // 实例化Socket对象,就是与远端计算机建立连接的过程
        // 需要传递两个对数:
        // 1.远端计算机的IP地址,用于找到网络上对方的计算机
        // 2.远端计算机的端口号,用于找到对方计算机中的应用程序
        try {
            System.out.println("正在连接服务端......");
            /**
             * 如何查找本机IP地址:
             * Windows:Win+R,输入cmd,回车,输入ipconfig,回车
             * Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址
             */
            socket = new Socket("172.40.140.102", 8088);
            System.out.println("连接成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 该方法用于启动客户端程序的执行
    public void start() {
        // 通过Socket获取输出流用于向服务端发送消息
        try {
            OutputStream outputStream = socket.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            PrintWriter printWriter = new PrintWriter(bufferedWriter,true);  // 自动行刷新
            Scanner scanner = new Scanner(System.in);
            while (true) {
                String line = scanner.nextLine();
                if ("exit".equalsIgnoreCase(line)) {
                    break;
                }
                printWriter.println(line);  // 发送消息给服务端
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }
}

三次握手与四次挥手

客户端断开连接的操作

  • 我们在上方代码中输入“exit”后,服务器会出现一大堆红字;

什么是三次握手四次挥手

  • 异常出现的原因:

    • TCP协议是面向连续的可靠传输协议,双方建立连接及断开连接需要双向确认后才可以进行

    • 当任意一方在没有进行确认断开操作就擅自结束,另一方就会出现该异常。

  • 三次握手与四次挥手:

    • 客户端与服务端建立TCP连接时需要进行三次握手,以确保双方可以建立可靠连接;

    • 任意一方需要断开TCP连接时需要进行四次挥手,以确保双方可靠断开。

三次握手(Three-way Handshake)

  • 第一次握手(SYN):

    • 客户端发送一个带有SYN(同步)标志的数据包到服务器,并指定客户端的初始化序列号(ISN);

    • 客户端进入SYN_SENT状态,以等待服务器的确认。

  • 第二次握手(SYN-ACK):

    • 服务器收到客户端的SYN数据包后,会发送一个带有SYNACK(确认)标志的数据包到客户端,确认客户端的请求,并指定服务器的初始化序列号(ISN)。

    • 服务器进入SYN_RCVD状态;

  • 第三次握手(ACK):

    • 客户端收到服务器的SYN-ACK数据包后,会发送一个带有ACK标志的数据包给服务器,表示确认连线请求;

    • 服务器收到客户端的ACK后,双方都进入ESTABLISHED状态,建立起可靠的连接。

在这里插入图片描述

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

四次挥手(Four-way Wavehake)

  • Socket提供方法:

    • void close():用于和对方断开TCP连接,底层会进行四次挥手操作。

在这里插入图片描述

  1. 客户端发送FIN报文:客户端首先向服务器发送一个带有FIN标志位的保温,表示客户端不再发送数据,并请求关闭连接。此时客户端进入“FIN_WAIT_1”状态;

  2. 服务器发送ACK报文:服务器收到客户端的FIN报文后,会发送一个确认保温,即ACK报文,告知客户端已经收到关闭请求。此时服务器进入“CLOSE_WAIT”状态,等待确认关闭;

  3. 服务器发送FIN报文:服务器在发送ACK报文后,会继续检查是否还有剩余的数据需要发送。如果有,服务器会继续发送数据;如果没有,服务器会发送一个带有FIN标志位的报文给客户端,表示服务器也不在发送数据了。此时服务及进入“LAST_ACK”状态;

  4. 客户端发送ACK报文:客户端收到服务器的FIN报文后,会发送一个确认报文,即ACK报文,告知服务器已经收到关闭请求,并进入“TIME_WAIT”状态。再“TIME_WAIT”状态下,客户端等待一段时间(通常为2倍的最大报文段生存时间,即MSL),以确保服务器已经收到了ACK报文;

  5. 服务器收到ACK报文:服务器收到客户端的ACK报文后,确认客户端已经收到了服务器的关闭请求,此时服务器进入“CLOSED”状态,完成连接的关闭。

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

 package day18;
 import java.io.*;
 import java.net.Socket;
 import java.nio.charset.StandardCharsets;
 import java.util.Scanner;
 
 /**
  * 客户端
  */
 public class Client {
     /**
      * java.net.Socket:套接字
      * 它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互
      * 可以理解为是电话
      */
     private Socket socket;
     public Client() {
         // 实例化Socket对象,就是与远端计算机建立连接的过程
         // 需要传递两个对数:
         // 1.远端计算机的IP地址,用于找到网络上对方的计算机
         // 2.远端计算机的端口号,用于找到对方计算机中的应用程序
         try {
             System.out.println("正在连接服务端......");
             /**
              * 如何查找本机IP地址:
              * Windows:Win+R,输入cmd,回车,输入ipconfig,回车
              * Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址
              */
             socket = new Socket("localhost", 8888);
             System.out.println("连接成功!");
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 
     // 该方法用于启动客户端程序的执行
     public void start() {
         // 通过Socket获取输出流用于向服务端发送消息
         try {
             OutputStream outputStream = socket.getOutputStream();
             OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
             BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
             PrintWriter printWriter = new PrintWriter(bufferedWriter,true);  // 自动行刷新
             Scanner scanner = new Scanner(System.in);
             while (true) {
                 String line = scanner.nextLine();
                 if ("exit".equalsIgnoreCase(line)) {
                     break;
                 }
                 printWriter.println(line);  // 发送消息给服务端
             }
 
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             try {
                 socket.close();  // 进行四次挥手
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
 
     public static void main(String[] args) {
         Client client = new Client();
         client.start();
     }
 }
 

多线程

概念

什么是线程与多线程

  • 线程是一个单一的顺序执行流程;

  • 多线程是多个单一顺序执行流程一起执行。

顺序执行与并发执行

  • 顺序执行:程序从上至下一句一句执行;

  • 并发执行:多个线程一起执行称为“并发执行”。

使用场景

  • 互不干扰:多线程通常用于在一个程序中需要同时处理多个互不干扰的任务;

  • 多线程更快:单线程可以完成,但是多线程更快。

单线程和多线程比喻

  • 可以把单线程看作只有一个灶台,一次只能做一道菜;或看作电路中的串联;

  • 多线程则是有很多灶台,一次能做很多菜;或看作电路中的并联。

CPU与多线程

CPU 的多线程操作通过时间片轮转Time Slicing)来实现。虽然一个 CPU 在某一时刻只能执行一个线程,但它可以在多个线程之间快速切换,使得每个线程都能获得一定的执行时间。这种快速的切换让用户感觉多个线程是同时运行的。

线程的创建

第一种创建线程形式

  • 继承Thread来定义一个线程:

    • 重写run方法,在其中定义该线程的任务代码。
 package day18;
 
 /**
  * 线程的第一种创建方式:继承Thread类
  * 更方便地使用匿名内部类创建线程、结构简单
  * 缺点:Java是单继承的,所以不能再继承其他类
  *      意味着继承了Thread就无法再继承其他类了,不利于复用
  *      定义线程的同时定义了线程的任务,导致线程和任务绑定在了一起,不利于复用
  */
 public class ThreadDemo01 {
     public static void main(String[] args) {
         Thread thread01 = new MyThread01();
         Thread thread02 = new MyThread02();
         // 启动线程要调用star(),而不是直接调用run()方法
         thread01.start();
         thread02.start();
     }
 }
 
 class MyThread01 extends Thread {
     public void run() {
         for (int i = 0; i < 1000; i++) {
             System.out.println("Hi!" + i);
         }
     }
 }
 
 class MyThread02 extends Thread {
     public void run() {
         for (int i = 0; i < 1000; i++) {
             System.out.println("ByeBye!" + i);
         }
     }
 }
 

第二种创建线程的方式

  • 启动线程:

    • 实例化线程任务;

    • 实例化线程,同时将任务通过现成的构造器传递给线程;

    • 调用线程的start()方法。

 package day18;
 
 /**
  * 第二种创建线程的方式:实现Runnable接口
  */
 public class ThreadDemo02 {
     public static void main(String[] args) {
         // 创建线程任务
         Runnable runnable01 = new MyRunnable01();
         Runnable runnable02 = new MyRunnable02();
         // 创建线程
         Thread thread01 = new Thread(runnable01);
         Thread thread02 = new Thread(runnable02);
         // 启动线程
         thread01.start();
         thread02.start();
     }
 }
 
 class MyRunnable01 implements Runnable {
     @Override
     public void run() {
         for (int i = 1; i <= 1000; i++) {
             System.out.println("Hello!" + i);
         }
     }
 }
 
 class MyRunnable02 implements Runnable {
     @Override
     public void run() {
         for (int i = 1; i <= 1000; i++) {
             System.out.println("Hi!" + i);
         }
     }
 }

使用匿名内部类实现线程的两种创建方式

 package day18;
 
 /**
  * 使用匿名内部类方式实现线程的两种创建方式
  */
 public class ThreadDemo03 {
     public static void main(String[] args) {
         //第一种创建方式:继承Thread并重写run方法
         Thread thread01 = new Thread() {
             public void run() {
                 for (int i = 0; i < 100; i++) {
                     System.out.println("线程01:" + i);
                 }
             }
         };
         thread01.start();
         //第二种创建方式:实现Runnable接口并重写run方法
         Thread thread02 = new Thread(() -> {
             for (int i = 0; i < 100; i++) {
                 System.out.println("线程02:" + i);
             }
         });
         thread02.start();
     }
 }
 

并发解决聊天室不能多用户使用问题

 package day18;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.nio.charset.StandardCharsets;
 
 /**
  * 服务端
  */
 public class Server {
     /**
      * java.net.ServerSocket:
      * 运行在服务端,主要作用有两个:
      * 1.像系统申请服务端口,客户端通过该端口与服务端建立连接
      * 2.监听服务端口,一旦有客户链接了,就会立即创建一个Socket对象与客户端进行交互
      *      如果将Socket比喻为“电话”,那ServerSocket就相当于客户中心的“总机”。
      * 解决方法:
      * 1.更换端口号;
      * 2.杀死占用该端口的进行(通常由于服务端启动了两次导致)
      */
     private ServerSocket serverSocket;
     public Server(){
         try {
             System.out.println("正在启动服务端......");
             serverSocket = new ServerSocket(8888);
             System.out.println("服务端启动完成!");
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 
     // 启动服务端方法:
     /**
      * accept():
      * 用于接收客户端连接,并返回一个Socket对象与所连接的客户端进行交互
      * 该方法是一个阻塞方法,调用后程序会“卡住”,直到一个客户端连接为止
      */
     public void start(){
         try {
             while (true){
                 System.out.println("服务端正在等待客户端连接......");
                 Socket socket = serverSocket.accept();
                 System.out.println("一个客户端连接了!");
                 
                 // 启动单独的线程来处理与客户端的通信
                 ClientHandler clientHandler = new ClientHandler(socket);
                 Thread thread = new Thread(clientHandler);
                 thread.start();
             }
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
     public static void main(String[] args) {
         Server server = new Server();
         server.start();
     }
 
     /**
      * 该线程任务用于负责与指定的客户端通信
      */
     private class ClientHandler implements Runnable{
         private Socket socket;
         public ClientHandler(Socket socket) {
             this.socket = socket;
         }
 
         @Override
         public void run() {
             try {
                 // 接收客户端发送过来的消息
                 InputStream inputStream = socket.getInputStream();
                 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                 String message;
                 while ((message = bufferedReader.readLine()) != null) {    // 读取客户端发送过来的消息
                     System.out.println("客户端说:" + message);
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             } finally {
                 try {
                     serverSocket.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
 }
 

主线程

  • Java程序的任何代码都是靠线程进行,main方法也是;

  • 程序启动后,JVM创建一条线程执行main方法,这条线程我们叫“主线程main”;

什么是主线程

  • Thread提供的静态方法:

    • static Thread currentThread()

    • 该方法用于返回执行他的线程;

查看线程的相关信息

  • Thread提供了获取线程信息的相关方法:

    • long getId():返回该线程的标识符;

    • String getName():返回该线程的名称;

    • int getPriority():返回线程的优先级;

    • boolean isAlive():检测线程是否处于活跃状态;

    • boolean isDeamon():测试线程是否为守护线程;

    • boolean isInterrupted():测试线程是否已经中断;

 package day18;
 
 import static java.lang.Thread.currentThread;
 
 /**
  * 线程信息
  */
 public class ThreadInfoDemo {
     public static void main(String[] args) {
         Thread main = currentThread();  // 获取主线程
         System.out.println(main);
         doSome();  // 主线程调用doSome方法
     }
 
     public static void doSome() {
         Thread t = currentThread();  // 获取的是doSome方法的线程
         System.out.println("运行doSome方法的线程:" + t);
         System.out.println("运行doSome方法的线程名称:" + t.getName());
         System.out.println("运行doSome方法的线程优先级:" + t.getPriority());
         System.out.println("运行doSome方法的线程是否是守护线程:" + t.isDaemon());
         System.out.println("运行doSome方法的线程是否是活动线程:" + t.isAlive());
         System.out.println("运行doSome方法的线程是否是中断状态:" + t.isInterrupted());
         System.out.println("运行doSome方法的线程标识符:" + t.getId());
     }
 
 }
 

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

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

相关文章

使用 Arch Linux 几个月有感 | 为什么我选择 Arch Linux ,Arch 的优缺点有什么 | 一些Linux发行版推荐

&#xff08;终端是 Yakuake &#xff0c;KDE 自带&#xff09; 一点碎碎念&#xff0c;可以跳过不看 几年前从 CentOS 接触的 Linux &#xff0c;试图搭建一个KMS服务器 但是失败了 &#xff0c;后来装过 Ubuntu Debian deepin Kali Kubuntu Manjaro&#xff0c;踩一路坑最后…

线性数据结构的基本概念(数组,链表,栈,队列)

数组 数组由相同类型的元素组成&#xff0c;使用一块连续的内存来存储。 数组的特点是&#xff1a; 1.利用索引进行访问 2.容量固定 3.使用一块连续的内存来存储 各种操作的时间复杂度&#xff1a; 查找/修改&#xff1a;O&#xff08;1&#xff09;//访问特定位置的元素 插入…

day07_算法训练

案例零&#xff1a;整数反转&#xff08;大整数算法&#xff09; 给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 暂时不用考虑数据太大的问题&#xff0c;把本题的核心思路写出来即可 比如&#xff1a; ​ 输入&#xff1a;x 123 ​ 输出…

一分钟带你了解叉车!

一、叉车的概念 叉车是指对整件托盘货物或大件桶装进行装卸、堆垛和短距离运输作业的各种搬运车辆。叉车是实现整件货物和散装物料机械化装卸、堆垛和短途运输的高效率工作车辆。 叉车常用于仓储大型物件的运输、车站、码头、机场、仓库、工地、货厂和工矿企业&#xff0c;是…

【案例47】enq: TX - row lock contention事件导致制单卡死

问题现象 制单时&#xff0c;选择公司就会卡住不动&#xff0c;其他节点正常。 问题分析 通过nmc排查&#xff0c;发现后台有很多制单线程卡住&#xff0c;时间较久&#xff0c;并且当前的事件都是在数据库执行sql层面。并且每条线程的卡住语句都为update语句&#xff0c;怀…

Openstack 与 Ceph集群搭建(中): Ceph部署

文章目录 一、部署前说明1. ceph 版本选择依据2. ceph网络要求3. 硬件要求 二、部署架构三、部署过程1. 通用步骤2. 部署管理节点创建账号安装Cephadm运行bootstrap 3. 登录Ceph web4. 将其他节点加入集群同步ceph key安装ceph CLI命令行添加主机节点到集群添加OSD节点将监控节…

[数据集][目标检测]机械常用工具检测数据集VOC+YOLO格式4713张8类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4713 标注数量(xml文件个数)&#xff1a;4713 标注数量(txt文件个数)&#xff1a;4713 标注…

配置typora上传图片到Chevereto图床

目录 一、下载安装PicGo二、配置PicGo三、配置Typora 一、下载安装PicGo PicGo下载地址点击进入 进入官网后点击下载&#xff0c;会跳转到GitHub,如图,选择对应的操作系统版本下载 下载完成后单击安装&#xff08;本文已windows系统为例&#xff09; 二、配置PicGo 点击插件设…

华为OD机试 - 密码输入检测 字符串

只在本地跑过&#xff0c;不确保一定对 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h>#define setbit(value,bit) (value value |(1<<bit))int main(void) {char buf[201];char out[201];int i 0;int to…

UploadLabs靶场环境

目录 UploadLabs靶场环境 第十八题 第十九题 第二十一题 UploadLabs靶场环境 .php .php. . 第五&#xff0c;十关访问的时候空格必须要使用 %20代替 第七题在linux服务器上的话&#xff0c;文件名如果末尾只存在空格并不会自动删除&#xff0c;还会保留&#xff0c;但是这…

合宙Air700ECQ硬件设计手册——应用接口1

Air700ECQ是一款高度集成的LTE Cat1无线通信模组&#xff0c;基于移芯EC716E平台设计&#xff0c;有着极小的封装和极高的性价比。 它支持移动双模FDD-LTE/TDD-LTE 4G远距离无线传输技术&#xff0c;能够广泛应用于共享设备、定位器、DTU数传等多种场景。 此外&#xff0c;Air7…

2024年互联网公司时薪排行榜大曝光!

2024年互联网公司时薪排行榜重磅出炉&#xff01;这一次&#xff0c;行业薪资数据的透明度前所未有&#xff0c;看完这份榜单&#xff0c;你会发现互联网圈子的贫富差距竟然如此悬殊&#xff0c;不禁让人直呼“酸了”&#xff01; 在这个人人都关注收入与回报的时代&#xff0…

算法之工程化内容(3)—— Docker常用命令

目录 1. 配置docker镜像加速 2. 创建镜像docker-name 3. 查看正在运行的镜像 4. 拉取镜像 5. 运行镜像 6. 停止/启动指定 id 的容器 7. 删除指定 id 的镜像/容器 8. docker发布和部署 (推荐教程&#xff1a;&#x1f69a; 发布和部署 - Docker 快速入门) 1. 配置docke…

CentOS上安装和配置Docker与Docker Compose的详细指南

引言 大家好&#xff0c;我是小阳&#xff0c;在这篇文章中&#xff0c;我将带大家一步步完成在CentOS系统上安装和配置Docker与Docker Compose的过程。通过这篇详细的指南&#xff0c;你将能够轻松配置Docker环境&#xff0c;并在日常开发和部署中享受其带来的便利。 原文阅…

一行一行代码带你阅读,xxljob, 若依vue基础项目,若依vue-plus 项目,实战项目的 视频课程

目录 1 介绍2 地址 1 介绍 本人自己录制的一行一行代码解释源码的课程&#xff0c;适合小白&#xff0c;么有阅读过源码&#xff0c;或者不知道咋阅读源码的小伙伴。 本课程 有&#xff0c;视频&#xff0c;笔记&#xff0c;加了注释的源码 2 地址 1 实战课程 本课程 有&am…

拓客工具,助你多维度筛选客源!

随着大数据与人工智能技术的飞速发展&#xff0c;企业拓客的方式也迎来了前所未有的变革。在这里将分享如何利用拓客工具&#xff0c;在任意行业中精实现高效拓客。 一、高级搜索&#xff1a;最新企业&#xff01; 传统的客户开发方式往往依赖于广撒网式的营销手段&#xff0c;…

Linux系统-打包重定向/管道符/进程shell脚本

打包、解包、压缩、解压缩命令 统一使用tar命令&#xff0c;根据不同的参数完成不同的操作 语法&#xff1a;tar 参数 打包后的文件(只能是一个) 需要打包的文件或目录(可以是多个&#xff0c;空格分开即可) 常见的打包压缩格式&#xff1a; 打包后的文件后缀名&#xff1a;…

Linux——网络(1)

一、IPC&#xff08;进程间通信方式&#xff09; IPC&#xff1a;Inter Process Communication 共享内存&#xff08;最高效的进程间通信方式&#xff09; 虚拟地址 mmu(memory management unit ) 共享内存: 1.是一块&#xff0c;内核预留的空间 2.最高效的…

攻击手法罕见!ESET披露最新网络钓鱼活动,专门针对Android、iPhone用户

ESET 研究人员发现了一种罕见的网络钓鱼活动&#xff0c;专门针对 Android 和 iPhone 用户。他们分析了一个在野外观察到的案例&#xff0c;该案例主要是针对一家著名的捷克银行的客户。 值得注意的是这种攻击主要是从第三方网站安装钓鱼应用程序&#xff0c;而无需用户主动安…

东方博宜OJ 训练计划:前缀和、差分 习题集

前缀和、差分 听到这个名字&#xff0c;大家一定感觉不陌生吧&#xff0c;毕竟学过动态规划的人大部分 都知道&#xff0c;那我就简单介绍一下&#xff0c;并奉上习题供大家参考&#xff01; 题目描述我就不放了&#xff0c;根据题号参见 东方博宜OJ 东方博宜OJ 网址&#xf…