Java 网络编程入门

文章目录

    • 一、网络编程入门
      • 1. 网络编程三要素
      • 2. IP 地址
      • 3. InetAddress
      • 4. 端口
      • 5. 协议
    • 二、UDP 通信程序
      • 1. UDP 发送数据
      • 2. UDP 接收数据
      • 3. UDP 案例
    • 三、TCP 通信程序
      • 1. TCP 发送数据
      • 2. TCP 接收数据
      • 3. 服务器给出反馈
      • 4. 客户端录入键盘数据
      • 5. 服务器数据写入文件
      • 6. 客户端数据来自文件
      • 7. 文件上传并给出反馈
      • 8. 多线程实现上传文件

一、网络编程入门

网络编程:在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。

1. 网络编程三要素

① IP 地址
要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,而 IP 地址就是这个标识号,也就是设备的 标识。

② 端口
网络的通信,本质上是两个应用程序的通信。每台计算机都有很多的应用程序,那么在网络通信时,如何区分这些应用程序呢?如果说 IP 地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的应用程序了,也就是应用程序的标识。

③ 协议
通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换,常见的协议有 UDP 协议和 TCP 协议。

2. IP 地址

IP 地址是网络中设备的唯一标识。

IP 地址分为两大类:

IPv4:是给每个连接在网络上的主机分配一个 32bit 地址。按照 TCP/IP 规定,IP 地址用二进制来表示,每个 IP 地址长32bit,也就是 4 个字节,例如一个采用二进制形式的 IP 地址是 “11000000 10101000 00000001 01000010”,这么长的地址,处理起来也太费劲了。为了方便使用,IP 地址经常被写成十进制的形式,中间使用符号 “.” 分隔不同的字节,于是,上面的 IP 地址可以表示为 “192.168.1.66”。IP 地址的这种表示法叫做 “点分十进制表示法”,这显然比 1 和 0 容易记忆很多。

IPv6:由于互联网的蓬勃发展,IP 地址的需求量越来越多,但是网络地址资源是有限的,使得 IP 地址的分配越发紧张。为了扩大地址空间,通过 IPv6 重新定义地址空间,采用 128 位地址长度,每 16 个字节一组,分成 8 组十六进制数,这样就解决了网络地址资源数量不够的问题。

常用命令:
① ipconfig:查看本机 IP 地址;
② ping IP 地址:检查网络是否连通。

win+R 键,输入 cmd 进入命令行!

在这里插入图片描述

在这里插入图片描述

特殊 IP 地址 127.0.0.1,是回送地址,可以代表本机地址,一般用来测试使用!

3. InetAddress

为了方便我们对 IP 地址的获取和操作,Java 提供了一个类 InetAddress 供我们使用,此类表示 Internet 协议地址。
在这里插入图片描述


package com.zxe;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class Test {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address = InetAddress.getByName("LAPTOP-5061KU8Q");
        String name = address.getHostName();
        String ip = address.getHostAddress();
        System.out.println("主机名是:" + name);
        System.out.println("IP地址是:" + ip);
    }
}

在这里插入图片描述

我们可以直接传入主机名,也可以通过传 IP 地址的方式来获取 InetAddress 对象:

InetAddress address = InetAddress.getByName("192.168.207.1");

4. 端口

端口:设备上应用程序的唯一标识。
端口号:用两个字节表示的整数,它的取值范围是 0 ~ 65535。其中,0 ~ 1023 之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用 1024 以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

5. 协议

协议:计算机网络中,连接和通信的规则被称为网络通信协议。

① UDP 协议

用户数据报协议。
UDP 是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
例如视频会议通常采用 UDP 协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大的影响。但是在使用 UDP 协议传送数据时,由于 UDP 的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用 UDP 协议。

由于使用 UDP 协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输。

② TCP 协议

传输控制协议。
TCP 协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在 TCP 连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过 “三次握手”。
三次握手:TCP 协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。第一次握手,客户端向服务器端发出连接请求,等待服务器确认;第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求;第三次握手,客户端再次向服务器端发送确认信息,确认连接。

在这里插入图片描述

完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了,由于这种面向对象连接的特性,TCP 协议可以保证传输数据的安全,所以应用十分广泛,例如上传文件、下载文件、浏览网页等。

二、UDP 通信程序

UDP 协议是一种不可靠的网络协议,它在通信的两端各建立一个 Socket 对象,但是这两个 Socket 只是发送、接收数据的对象,因此对于基于 UDP 协议的通信双方而言,没有所谓的客户端和服务器的概念。

Java 提供了 DatagramSocket 类作为基于 UDP 协议的 Socket。

1. UDP 发送数据

发送数据的步骤:
① 创建发送端的 Socket 对象(DatagramSocket);
② 创建数据,并把数据打包;
③ 调用 DatagramSocket 对象的方法发送数据;
④ 关闭发送端。


package com.zxe;

import java.io.IOException;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        //创建发送端的Socket对象
        DatagramSocket ds = new DatagramSocket();
        //创建数据,并把数据打包,DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        byte[] bys = "嗨UDP,我来啦!".getBytes();
        int length = bys.length;
        InetAddress address = InetAddress.getByName("LAPTOP-5061KU8Q");
        int port = 10072;
        DatagramPacket dp = new DatagramPacket(bys, length, address, port);
        //调用DatagramSocket对象的send方法发送数据
        ds.send(dp);
        //关闭发送端
        ds.close();
    }
}

2. UDP 接收数据

接收数据的步骤:
① 创建接收端的 Socket 对象(DatagramSocket);
② 创建一个数据包,用于接收数据;
③ 调用 DatagramSocket 对象的方法接收数据;
④ 解析数据包,并把数据在控制台显示,byte[] getData() 返回数据缓冲区;
⑤ 关闭接收端。


package com.zxe;

import java.io.IOException;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        //创建接收端的Socket对象
        DatagramSocket ds = new DatagramSocket(10072);
        //创建一个数据包,用于接收数据,DatagramPacket(byte[] buf, int length)
        byte[] bys = new byte[1024];
        int length = bys.length;
        DatagramPacket dp = new DatagramPacket(bys, length);
        //调用DatagramSocket对象的receive方法接收数据
        ds.receive(dp);
        //解析数据包,并把数据在控制台显示,byte[] getData() 返回数据缓冲区
        byte[] datas = dp.getData();
        //getLength()返回实际接收到的数据的长度,因为实际数据的长度不一定是1024
        int len = dp.getLength();
        String dataString = new String(datas, 0, len);
        System.out.println("数据是:" + dataString);
        //关闭接收端
        ds.close();
    }
}

在这里插入图片描述

接收端在创建 Socket 对象时要传入指定的端口号,运行时要先执行接收端,再执行发送端,同时注意此 IP 是本机的 IP!

3. UDP 案例

要求:数据来自于键盘录入,直到输入的数据是 886,发送数据结束,因为接收端不知道发送端什么时候停止发送,故采用死循环接收。

package com.zxe;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {

        DatagramSocket ds = new DatagramSocket();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = br.readLine()) != null) {
            if (line.equals("886")) {
                break;
            }
            byte[] bys = line.getBytes();
            InetAddress address = InetAddress.getByName("LAPTOP-5061KU8Q");
            DatagramPacket dp = new DatagramPacket(bys, bys.length, address, 10072);
            ds.send(dp);
        }
        ds.close();
    }
}

package com.zxe;

import java.io.IOException;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {

        DatagramSocket ds = new DatagramSocket(10072);
        while (true) {
            byte[] bys = new byte[1024];
            int length = bys.length;
            DatagramPacket dp = new DatagramPacket(bys, length);
            ds.receive(dp);
            byte[] datas = dp.getData();
            int len = dp.getLength();
            String dataString = new String(datas, 0, len);
            System.out.println("数据是:" + dataString);
        }
    }
}

在这里插入图片描述

在这里插入图片描述

你也可以同时运行多个发送端给一个接收端发送数据:

在这里插入图片描述

如何在 idea 开启多个控制台?
idea 页面上边菜单栏,Run → Edit Configurations → Modify options → 把 Allow multiple instances 勾上 → Apply。

三、TCP 通信程序

TCP 通信协议是一种可靠的网络协议,它在通信的两端各建立一个 Socket 对象,从而在通信的两端形成网络虚拟链路,两端的程序就可以通过虚拟链路进行通信。
Java 对基于 TCP 协议的网络提供了良好的封装,使用 Socket 对象来代表两端的通信端口,并通过 Socket 产生 IO 流来进行网络通信。
Java 为客户端提供了 Socket 类,为服务器端提供了 ServerSocket 类。

1. TCP 发送数据

发送数据的步骤:
① 创建客户端的 Socket 对象(Socket);
② 获取输出流,写数据;
③ 释放资源


package com.zxe;

import java.io.IOException;
import java.io.OutputStream;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        OutputStream os = s.getOutputStream();
        os.write("嗨TCP,我来啦!".getBytes());
        s.close();
    }
}

在这里插入图片描述

这里直接运行是会报错的,因为我们的 TCP 是要进行三次握手的,目前没有写服务器的程序,所以会报错!

2. TCP 接收数据

接收数据的步骤:
① 创建服务器端的 Socket 对象(ServerSocket);
② 监听客户端连接,返回一个 Socket 对象;
③ 获取输入流,读数据,并把数据显示在控制台;
④ 释放资源。


package com.zxe;

import java.io.IOException;
import java.io.InputStream;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        Socket s = ss.accept();
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys, 0, len);
        System.out.println("数据是:" + data);
        ss.close();
    }
}

accept() 监听到客户端有连接,就生成一个 Socket 对象!

3. 服务器给出反馈

需求:客户端发送数据,接收服务器反馈,服务器接收数据,给出反馈。


package com.zxe;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        //给服务器发送数据
        OutputStream os = s.getOutputStream();
        os.write("嗨TCP,我来啦!".getBytes());
        //接收服务器的反馈
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys, 0, len);
        System.out.println("客户端收到反馈:" + data);
        s.close();
    }
}


package com.zxe;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        Socket s = ss.accept();
        //服务器接收到数据
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);
        String data = new String(bys, 0, len);
        System.out.println("数据是:" + data);
        //服务器给出反馈
        OutputStream os = s.getOutputStream();
        os.write("数据成功收到!".getBytes());
        ss.close();
    }
}

在这里插入图片描述

在这里插入图片描述

4. 客户端录入键盘数据

需求:客户端数据来自于键盘录入,直到输入的数据是 886,发送数据结束,服务器接收的数据在控制台输出。


package com.zxe;

import java.io.*;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        //键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //封装输出流对象,将字节输出流转换为字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            if (line.equals("886")) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.close();
    }
}


package com.zxe;

import java.io.*;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        Socket s = ss.accept();
        //为了能一次读取一行,我们把字节缓冲流包装成字符缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println("数据是:" + line);
        }
        ss.close();
    }
}

在这里插入图片描述

5. 服务器数据写入文件

需求:客户端数据来自于键盘录入,直到输入的数据是 886,发送数据结束,服务器接收到的数据写入文本文件。


package com.zxe;

import java.io.*;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        Socket s = ss.accept();
        //为了能一次读取一行,我们把字节缓冲流包装成字符缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\myReceive.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        ss.close();
    }
}

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

客户端代码与上一案例一样,这里仅展示服务器端代码!

6. 客户端数据来自文件

需求:客户端数据来自文本文件,服务器接收到的数据写入文本文件。


package com.zxe;

import java.io.*;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\mySend.txt"));
        //封装输出流对象,将字节输出流转换为字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        s.close();
    }
}

在这里插入图片描述

服务器端代码与上一案例一致,这里仅展示客户端代码!

7. 文件上传并给出反馈

需求:服务器数据来自于文本文件,接收服务器反馈,服务器将接收到的数据写入文本文件,并给出反馈。


package com.zxe;

import java.io.*;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\mySend.txt"));
        //封装输出流对象,将字节输出流转换为字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.shutdownOutput();
        BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String data = brClient.readLine();
        System.out.println("服务器给出的反馈:" + data);
        br.close();
        s.close();
    }
}


package com.zxe;

import java.io.*;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        Socket s = ss.accept();
        //为了能一次读取一行,我们把字节缓冲流包装成字符缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\myReceive.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        bwServer.write("文件上传成功!");
        bwServer.newLine();
        bwServer.flush();
        bw.close();
        ss.close();
    }
}

在这里插入图片描述

shutdownOutput() 自定义结束标记,可以中断输出流,告诉服务器我已发送完毕了,但并不是关闭连接,客户端收到反馈的过程是一行一行读取的,所以服务器在给出反馈后一定要另起一行并刷新一下!

8. 多线程实现上传文件

需求:客户端数据来自于文本文件,接收服务器反馈,服务器将接收到的数据写到文本文件,并给出反馈,代码使用线程进行封装,为每一个客户端开启一个线程。

//ServerThread.java

package com.zxe;

import java.io.*;
import java.net.Socket;

public class ServerThread implements Runnable {
    private Socket s;

    public ServerThread(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            int count = 0;
            File file = new File("idea_test\\Copy[" + count + "].txt");
            while (file.exists()) {
                count++;
                file = new File("idea_test\\Copy[" + count + "].txt");
            }
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));
            String line;
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bwServer.write("文件上传成功!");
            bwServer.newLine();
            bwServer.flush();
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

//Send.java

package com.zxe;

import java.io.*;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("LAPTOP-5061KU8Q", 10023);
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\mySend.txt"));
        //封装输出流对象,将字节输出流转换为字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.shutdownOutput();
        BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String data = brClient.readLine();
        System.out.println("服务器给出的反馈:" + data);
        br.close();
        s.close();
    }
}

//Receive.java

package com.zxe;

import java.io.*;
import java.net.*;

public class Receive {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10023);
        while (true) {
            Socket s = ss.accept();
            ServerThread st = new ServerThread(s);
            Thread th = new Thread(st);
            th.start();
        }
    }
}

在这里插入图片描述

在这里插入图片描述

为了使每次所创建文件的文件名都不同,我们这里使用 count 变量来控制文件名称!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu使用vnc远程桌面【远程内网穿透】

文章目录1.前言2.两台互联电脑的设置2.1 Windows安装VNC2.2 Ubuntu安装VNC2.3.Ubuntu安装cpolar3.Cpolar设置3.1 Cpolar云端设置3.2.Cpolar本地设置4.公网访问测试5.结语1.前言 记得笔者刚刚开始接触电脑时,还是win95/98的时代,那时的电脑桌面刚迈入图形…

C++三种继承方式

C继承的一般语法为:class 派生类名:[继承方式] 基类名{派生类新增加的成员};继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected&#…

Python|蓝桥杯进阶第五卷——数论

欢迎交流学习~~ 专栏: 蓝桥杯Python组刷题日寄 蓝桥杯进阶系列: 🏆 Python | 蓝桥杯进阶第一卷——字符串 🔎 Python | 蓝桥杯进阶第二卷——贪心 💝 Python | 蓝桥杯进阶第三卷——动态规划 ✈️ Python | 蓝桥杯进阶…

Linux基本命令

相比Windows系统而言,在一般的企业开发中,使用linux系统无疑是更加广泛的,因此掌握常见的linux基本命令于我们来说是必要的,本文就是对Linux基本命令的简单介绍。 ls 列出当前目录下,所包含的目录及文件; …

学习系统编程No.9【文件操作】

引言: 北京时间:2023/3/23/6:34,可能是昨天充分意识到自己的摆烂,所以今天起的比较早一点吧!昨天摆烂的头号原因,笔试强训,加上今天4节课,可以说一整天都是课,所以能不能…

【CE进阶】lua脚本使用

▒ 目录 ▒🛫 导读需求开发环境1️⃣ 脚本窗口Lua ScriptLua EngineAuto assemble2️⃣ 全局变量3️⃣ 进程当前打开的进程ID系统的进程列表系统的顶部窗口列表4️⃣ 线程5️⃣ 输入设备6️⃣ 屏幕7️⃣ 剪贴板🛬 文章小结📖 参考资料&#x…

算法的时间复杂度和空间复杂度

目录 1 如何衡量一个算法的好坏 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3常见代码举例 2.3.1 Func2 O(N) 2.3.2 Func3 O(MN) 2.3.3 Func4 O(1) 2.3.4 Func5 strchr O(N) 2.3.5 Func6 冒泡排序 O(N^2) 2.3.6 Func7 二分…

菜鸟刷题Day6

⭐作者:别动我的饭 ⭐专栏:菜鸟刷题 ⭐标语:悟已往之不谏,知来者之可追 一.链表内指定区间反转:链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com) 描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转…

如何用深度强化学习做单元测试代码生成

设计一个用强化学习来生成单元测试代码的系统需要考虑以下几个方面: Agent:强化学习算法中的智能体,它需要接收当前环境状态,根据策略选择相应的动作并执行。 State:描述当前环境状态的特征。在这个问题中&#xff0c…

电脑长按电源键强行关机,对SSD有伤害吗?SSD 掉盘之殇

说到“按住电源键强制关机”的操作,想必大家都不会陌生,毕竟在电脑蓝屏或者电脑死机的时候,我们总是束手无策。而且,身边的人在遇到同样的情况时,往往都是选择长按电源键强制关机,所以当我们遇到同样的情况…

【算法】回溯法详解

一、概述 回溯法在包含的所有可能解的解空间树中,从根节点出发,按照深度有限的策略进行搜索,对于解空间树的某个结点,如果该节点满足问题的约束条件,则进入该子树继续进行搜索,否则将以该节点为根节点进行…

【算法】一文详解贪心法

一、概述 贪心法将一个复杂问题分解为一系列较为简单的局部最优解,每一步都是对当前解的一个扩展,直到获得问题的完全解。贪心法的典型应用时求解最优化问题,而且即使是非最优解,最终得出的解也和最优解比较近似 1.1 贪心法设计…

【多线程】常见的锁策略

✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:老当益壮,宁移白首之心;穷且益坚,不坠青云之志。 目 录🏳️一. 乐观锁 vs 悲观锁🏴二. 普通的互斥…

清晰概括:进程与线程间的区别的联系

相关阅读: 🔗通俗简介:操作系统之进程的管理与调度🔗如何使用 jconsole 查看Java进程中线程的详细信息? 目录 一、进程与线程 1、进程 2、线程 二、进程与线程之间的区别和联系 1、区别 2、联系 一、进程与线程 …

程序员接私活一定要知道的事情,我走的弯路你们都别走了

文章目录前言一、程序员私活的种类1.兼职职位众包2.自由职业者驻场3.项目整包二、这3种私活可以接1.有熟人2.七分熟的项目3.需求明确的项目三、这3种私活不要接1.主动找上门的中介单2.一味强调项目简单好做3.外行人给你拉的项目四、接单的渠道1.线下渠道2.线上渠道3.比较靠谱的…

计网之HTTP协议和Fiddler的使用

文章目录一. HTTP概述和fidder的使用1. 什么是HTTP2. 抓包工具fidder的使用2.1 注意事项2.2 fidder的使用二. HTTP协议格式1. HTTP请求格式1.1 基本格式1.2 认识URL1.3 方法2. 请求报头关键字段3. HTTP响应格式3.1 基本格式3.2 状态码一. HTTP概述和fidder的使用 1. 什么是HTT…

cpu中缓存简介

一级缓存是什么: 一级缓存都内置在CPU内部并与CPU同速运行,可以有效的提高CPU的运行效率。一级缓存越大,CPU的运行效率越高,但受到CPU内部结构的限制,一级缓存的容量都很小。 CPU缓存(Cache Memory&#xf…

【设计模式】23种设计模式之七大原则

【设计模式】23种设计模式之七大原则什么是设计模式的原则1、单一职责原则基本介绍案例分析注意事项2、接口隔离原则基本介绍案例分析代码实现3、依赖倒转原则基本介绍案例分析依赖传递的三种方式注意事项4、里氏替换原则关于继承性的思考和说明基本介绍案例分析5、开闭原则ocp…

冲击蓝桥杯-并查集,前缀和,字符串

目录 前言 一、并查集 1、并查集的合并(带路径压缩) 2、询问是否为同一个集合 3、例题 二、前缀和 1 、前缀和是什么 2、经典题目 三- 字符串处理 1、字符串的插入 2、字符串转化为int类型 3、字符反转 前言 并查集合前缀,字符串…

Python让ChatGPT全自动改写生成文章教程

ChatGPT是一个在自然语言处理领域非常先进的文本生成模型,它能够产生高质量、连贯的文章。它受到了广泛的关注,因为它可以自动生成大量的文本,从而减轻了人工写作的负担。怎么使用chatgpt批量改写文章?最简单的方式就是找到一家接…