Java学习路线(21)——网络通信

news2024/11/17 3:43:33

一、网络通信三件套
1、IP地址: 设备在网络中的地址,唯一标识

  • 概念: Internet Protocal,简称为IP,全称“互联网协议地址”。

  • 常见分类: IPv4(32位)IPv6(128位)

  • IP地址形式: 公网地址和私网地址(局域网),以192.168为开头的地址为常见的局域网地址。

  • 查看IP地址命令 ipconfig(windows):查看本机IP;ifconfig(linux/mac)

  • 查看IP是否通信: ping IP或是 ping 域名

  • 特殊IP地址: 127.0.0.1 或者 localhost,称为回送地址也称为本地回环地址,只会寻找当前本机

  • IP操作类-InetAddress

  • API方法

方法说明
static InetAddress getLocalHost()返回本主机的地址对象
static InetAddress getByName(String host)获取指定主机的IP地址对象,参数是域名或者IP地址
static String getHostName()返回IP地址的主机名
static String getHostAddress()返回IP地址字符串
static boolean isReachable(int timeout)在指定毫秒内连接IP地址对应的主机,连通返回true
  • 使用示例
public class InetAddressDemo {
    public static void main(String[] args) {
        try {
            /*1、获取本机地址对象*/
            InetAddress inetAddress = InetAddress.getLocalHost();
            System.out.println(inetAddress.toString());

            /*2、获取域名IP对象*/
            InetAddress inetAddress1 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress1.toString());

            /*3、获取主机名*/
            String hostname = InetAddress.getLocalHost().getHostName();
            System.out.println(hostname);

            /*4、获取公网IP地址*/
            String ip = InetAddress.getLocalHost().getHostAddress();
            System.out.println(ip);

            /*5、判断IP是否能通信*/
            boolean isPing = InetAddress.getByName("192.168.137.1").isReachable(5000);
            System.out.println(isPing);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/*打印输出*/
LAPTOP-76LAVL3O/192.168.xxx.xxx
www.baidu.com/180.101.50.242
LAPTOP-76LAVL3O
192.168.xxx.xxx
true

2、端口: 应用程序在设备中的唯一标识。

  • 概念: 标识正在计算机设备上运行的进程,被规定为一个16位的二进制,范围是0~65535
  • 端口类型:
    • 常用端口: 0~1023,例如HTTP:80,FTP:21
    • 注册端口(主要端口对象): 1024~49151,分配给用户进程或某些应用程序。如Tomcat:8080,MySQL:3306
    • 动态端口: 49152~65535,动态分配进程。

3、协议: 数据在网络中传输的规则

  • 概念: 连接和通信数据的规则称为网络通信规则。
  • 通信协议的两套参考模型:对照计算机网络对两种模型的介绍
    • OSI参考模型: 理想化的世界互联协议标准
    • TCP/IP参考模型: 事实上的国际标准
  • 常见协议
    • TCP协议(Transmission Control Protocol):传输控制协议

      • TCP协议特点:
        (1) 使用TCP,双方必须先建立连接,它是一种面向连接的可靠通信协议。
        (2) 传输前,采用 “三次握手” 方式建立连接,所以是可靠的。
        (3) 在连接中可以进行大量传输。
        (4) 连接、发送数据都需要确认,且传输完毕后,还需要释放连接,通信效率较低。
        • TCP协议通信场景: 对信息安全要求较高的场景,比如文件下载、金融等数据通信。
        • 三次握手:
          (1)第一次握手: 客户端向服务器发送连接请求,等待确认。
          (2)第二次握手: 服务器向客户端返回一个响应,向客户端确认收到连接请求。
          (3)第三次握手: 客户端向服务器发送确认信息,连接正式建立。
        • 为什么需要三次握手? 因为客户端和服务器要相互验证通信是否通畅,若有一次握手没有通过,则连接不建立。
        • 四次挥手断开连接
          (1)第一次挥手: 客户端向服务器发送取消连接请求
          (2)服务器向客户端返回一个响应表示收到请求
          (3)服务器向客户端发送确认取消信息
          (4)客户端向服务器发送确认信息,连接正式取消
    • UDP(User Datagram Protocol):用户数据报协议

      • UDP的特点
        (1)UDP是一种无连接、不可靠的传输协议
        (2)将数据源IP、目标IP和端口封装成数据包,不需要建立连接
        (3)每个数据包大小限制在64KB内
        (4)发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
        (5)可以广播发生,发送数据后无需释放资源,开销小,速度快
      • UDP使用场景: 语音通话,视频会话,直播等等…

二、UDP通信

1、数据包对象DatagramPacket创建

构造器说明
DatagramPacket(byte[] buf, int length, InetAddress address, int port )创建发送端数据包对象:buf——发送的内容,length——发送内容的字节长度,address——接收端的IP地址,port——接收端的端口号
DatagramPacket(byte[] buf, int length )创建接收端数据包对象:buf——接收内容,length——接收最大字节长度

2、发送端和接收端对象DatagramSocket创建

构造器说明
DatagramSocket()创建发送端的Socket对象,系统随机分配端口号
DatagramSocket(int port)创建接收端对象并指定端口号

3、发送/接收端对象操作数据包

方法说明
void send(DatagramPacket dp)发送数据包
void receive(DatagramPacket p)接收数据包

(1)单收单发数据示例

/*发送端*/
public class ClientDemo {
    public static void main(String[] args) {
        try {
            //1、创建发送对象
            DatagramSocket sender = new DatagramSocket();
            //2、数据包对象
            byte[] buf = "UDP数据报".getBytes();
            DatagramPacket data = new DatagramPacket(buf,buf.length, InetAddress.getLocalHost(),8888);
            //3、发送数据
            sender.send(data);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/*接收端*/
class ServerDemo{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            DatagramSocket accepter = new DatagramSocket(8888);
            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length);
            accepter.receive(datagramPacket);
            //3、打印数据
            System.out.println(new String(buf,0,datagramPacket.getLength()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/*打印输出*/
UDP数据报

(2)多发多收示例

public class ClientDemo {
    public static void main(String[] args) {
        try {
            //1、创建发送对象
            DatagramSocket sender = new DatagramSocket();
            byte[] buf;
            Scanner in = new Scanner(System.in);
            String message;
            DatagramPacket data;
            while(!(message = in.next()).equals("exit")) {
                //2、数据包对象
                buf = message.getBytes();
                data = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 8888);
                //3、发送数据
                sender.send(data);
            }

            message = "exit";
            buf = message.getBytes();
            data = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 8888);
            sender.send(data);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

class ServerDemo{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            DatagramSocket accepter = new DatagramSocket(8888);
            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket;
            while(true){
                datagramPacket = new DatagramPacket(buf,buf.length);
                accepter.receive(datagramPacket);
                if (new String(buf,0,datagramPacket.getLength()).equals("exit")) {
                    System.out.println("会话已结束");
                    break;
                }
                //3、打印数据
                System.out.println(new String(buf,0,datagramPacket.getLength()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果显示
在这里插入图片描述

问:实验中如何实现多端口通讯

答:事实上,我们可以直接使用不同的端口直接向接收端发送数据。

结果如图所示
在这里插入图片描述
4、UDP通信——广播、组播
(1)三种UDP通信方式

  • 单播: 单台主机与单台主机之间通信。
  • 广播: 当前主机与所在网络中的所有主机通信。
  • 组播: 当前主机与选定主机组通信

(2)UDP实现广播

  • 广播地址:255.255.255.255
  • 操作过程
    • 发送端发送的数据包目的地址是广播地址,且指定端口9999
    • 本机所在网段的其它主机的程序只要匹配端口成功就可以收到消息
public class BroadCastDemo {
    public static void main(String[] args) {
        try {
            //1、创建发送对象
            DatagramSocket sender = new DatagramSocket();
            byte[] buf;
            Scanner in = new Scanner(System.in);
            String message;
            DatagramPacket data;
            while(!(message = in.next()).equals("exit")) {
                //2、数据包对象
                buf = message.getBytes();
                data = new DatagramPacket(buf, buf.length, InetAddress.getByName("255.255.255.255"), 9999);
                //3、发送数据
                sender.send(data);
            }

            message = "exit";
            buf = message.getBytes();
            data = new DatagramPacket(buf, buf.length, InetAddress.getByName("255.255.255.255"), 9999);
            sender.send(data);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/*实验组*/
class ServerDemo1{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            DatagramSocket accepter = new DatagramSocket(9999);
            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket;
            while(true){
                datagramPacket = new DatagramPacket(buf,buf.length);
                accepter.receive(datagramPacket);
                if (new String(buf,0,datagramPacket.getLength()).equals("exit")) {
                    System.out.println("会话已结束");
                    break;
                }
                //3、打印数据
                System.out.println("IP地址:" + datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "发送数据:" + new String(buf,0,datagramPacket.getLength()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/*对照组*/
class ServerDemo2{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            DatagramSocket accepter = new DatagramSocket(8888);
            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket;
            while(true){
                datagramPacket = new DatagramPacket(buf,buf.length);
                accepter.receive(datagramPacket);
                if (new String(buf,0,datagramPacket.getLength()).equals("exit")) {
                    System.out.println("会话已结束");
                    break;
                }
                //3、打印数据
                System.out.println("IP地址:" + datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "发送数据:" + new String(buf,0,datagramPacket.getLength()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

效果图
在这里插入图片描述
(3)UDP实现组播

  • 组播地址: 224.0.0.0 ~ 239.255.255.255
  • 具体操作
    • 发送端数据包目的地址是组播IP(例如:224.0.1.1:9999)
    • 接收端必须绑定组播IP
    • DatagramSocket的子类MulticastSocket绑定组播IP
  • 示例
public class MutiCastDemo {
    public static void main(String[] args) {
        /*1、创建发送对象*/
        try {
            DatagramSocket sender = new DatagramSocket();
            DatagramPacket data;
            String message;
            Scanner scanner = new Scanner(System.in);
            byte[] buf;
            while(!(message = scanner.next()).equals("exit")){
                buf = message.getBytes();
                data = new DatagramPacket(buf, buf.length, InetAddress.getByName("224.0.1.1"),9999);
                sender.send(data);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

class ServerDemo3{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            MulticastSocket accepter = new MulticastSocket(9999);

            //绑定组播
            accepter.joinGroup(InetAddress.getByName("224.0.1.1"));

            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket;
            while(true){
                datagramPacket = new DatagramPacket(buf,buf.length);
                accepter.receive(datagramPacket);
                if (new String(buf,0,datagramPacket.getLength()).equals("exit")) {
                    System.out.println("会话已结束");
                    break;
                }
                //3、打印数据
                System.out.println("IP地址:" + datagramPacket.getSocketAddress() + "发送数据:" + new String(buf,0,datagramPacket.getLength()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

class ServerDemo4{
    public static void main(String[] args) {
        try {
            //1、创建接收对象
            MulticastSocket accepter = new MulticastSocket(9999);
            //绑定组播
            accepter.joinGroup(InetAddress.getByName("224.0.1.1"));
            //2、接收数据包对象
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket;
            while(true){
                datagramPacket = new DatagramPacket(buf,buf.length);
                accepter.receive(datagramPacket);
                if (new String(buf,0,datagramPacket.getLength()).equals("exit")) {
                    System.out.println("会话已结束");
                    break;
                }
                //3、打印数据
                System.out.println("IP地址:" + datagramPacket.getSocketAddress() + "发送数据:" + new String(buf,0,datagramPacket.getLength(),StandardCharsets.UTF_8));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

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

三、TCP通信
(1)实现方法:
TCP通信是通过C/S双方建立Socekt通道

  • 客户端

创建构造器

构造器说明
Socket(String host, int port)常见发送端的Socket对象与服务端连接,参数为服务端程序的IP和端口

方法

方法说明
OutputStream getOutputStream()获取字节输出流对象
InputStream getInputStream ()获取字节输入流对象
  • 服务端

服务端构造器

构造器说明
ServerSocket(int port)注册服务端口

方法

方法说明
Socket accept()等待Socket连接,连接成功后返回Socket对象

服务器端

/*服务端*/
class Server {
    public static void main(String[] args) {
        try {
            //1、建立通道
            ServerSocket socket = new ServerSocket(7777);

            //2、连接通道
            Socket connection = socket.accept();

            //3、读数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            String message;
            System.out.println(socket.getLocalSocketAddress() + " 连接成功,时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
            while ((message = reader.readLine()) != null) {
                System.out.println(socket.getInetAddress().getHostName() + "," + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()) + " : " + message);
            }
        } catch (SocketException socketException) {
            System.out.println("连接已中断");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

客户端

public class SocketDemo {
    public static void main(String[] args) {
        try {
            //1、建立通道
            Socket socket = new Socket(InetAddress.getLocalHost(), 7777);

            //2、发送数据
            PrintStream stream = new PrintStream(socket.getOutputStream());

            //3、写入数据
            String message;
            Scanner in = new Scanner(System.in);
            while (!(message = in.next()).equals("exit")) {
                stream.println(message);
                stream.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

效果图
在这里插入图片描述
(2)多客户端连接服务端

代码实现

public class SocketDemo {
    public static void main(String[] args) {
        try {
            //1、建立通道
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),7777);

            if (socket.isConnected()) System.out.println(socket.getRemoteSocketAddress() + " 已连接!");

            //2、发送数据
            PrintStream stream = new PrintStream(socket.getOutputStream());

            //3、写入数据
            String message;
            Scanner in = new Scanner(System.in);
            while (!(message = in.next()).equals("exit")) {
                stream.println(message);
                stream.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

class client{
    public static void main(String[] args) {
        try {
            //1、建立通道
            Socket socket = new Socket(InetAddress.getLoopbackAddress().getHostAddress(),7777);

            if (socket.isConnected()) System.out.println(socket.getRemoteSocketAddress() + " 已连接!");

            //2、发送数据
            PrintStream stream = new PrintStream(socket.getOutputStream());

            //3、写入数据
            String message;
            Scanner in = new Scanner(System.in);
            while (!(message = in.next()).equals("exit")) {
                stream.println(message);
                stream.flush();
            }
        } catch (IOException e) {
            System.out.println("连接已中断");
        }
    }
}

class Server {
    public static void main(String[] args) {
        try {
            //1、建立通道
            ServerSocket socket = new ServerSocket(7777);

            //2、连接通道
            while(true){
                Socket connection = socket.accept();
                new ServerServiceThread(connection,"服务器").start();
            }
        } catch (IOException e) {
            System.out.println("连接已中断");
        }
    }
}

class ServerServiceThread extends Thread{
    private Socket socket;

    public ServerServiceThread() {
    }

    public ServerServiceThread(Socket socket,String name) {
        super(name);
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String message;
            System.out.println(socket.getLocalSocketAddress() + " 连接成功,时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
            while ((message = reader.readLine()) != null) {
                System.out.println(socket.getInetAddress().getHostName() + "," + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()) + " : " + message);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "已下线!");
        }
    }
}

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

(3)线程池优化实现多客户端连接服务器

以下代码仅展示修改部分


class Server {
    public static void main(String[] args) {
        try {
            //1、建立通道
            ServerSocket socket = new ServerSocket(7777);

            ExecutorService service = new ThreadPoolExecutor(3,10,5, TimeUnit.SECONDS, new LinkedBlockingDeque<>(),new ThreadPoolExecutor.AbortPolicy());

            //2、连接通道
            while(true){
                Socket connection = socket.accept();
                service.execute(new ServerServiceThread(connection));
            }
        } catch (IOException e) {
            System.out.println("连接已中断");
        }
    }
}

class ServerServiceThread implements Runnable{
    private Socket socket;

    public ServerServiceThread() {
    }

    public ServerServiceThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String message;
            System.out.println(socket.getLocalSocketAddress() + " 连接成功,时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
            while ((message = reader.readLine()) != null) {
                System.out.println(socket.getInetAddress().getHostName() + "," + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()) + " : " + message);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "已下线!");
        }
    }
}

效果图
在这里插入图片描述
注意:我们可以从效果图里看出,外网IP与内网IP连接内网服务器的速度是不一样的。
外网: 本机——运营商——本机
内网: 本机——本机

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

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

相关文章

IDEA debug断点调试认识与技巧

IDEA debug断点调试认识与技巧 文章目录 IDEA debug断点调试认识与技巧认识debug常见的操作如何开启debug模式 基本用法和快捷键1、显示执行点&#xff08;Alt F10&#xff09;2、步过&#xff08;F8&#xff09;3、步入&#xff08;F7&#xff09;4、强制步入&#xff08;Alt…

【容器云架构】确定容器网络calico最佳网络选项

大图 了解 Calico 支持的不同网络选项&#xff0c;以便您可以根据需要选择最佳选项。 价值 Calico 灵活的模块化架构支持广泛的部署选项&#xff0c;因此您可以选择适合您特定环境和需求的最佳网络方法。这包括使用各种 CNI 和 IPAM 插件以及底层网络类型以非覆盖或覆盖模式运行…

线性回归模型一二三

文章目录 什么是线性回归线性回归的求解一元线性回归&#xff08;最小二乘法&#xff09;多元线性回归 衍生求解梯度下降智能搜索算法求解&#xff08;PSO&#xff09;简要分析 线性回归与简单神经网络联系类比推导反向传播 总结 什么是线性回归 线性回归的基本假设是&#xf…

Java JUC并发编程调优

前言 1、JUC是指有关 java.util.concurrent包以及其子包&#xff0c;这些包都是有关线程操作的包 2、HTTPS服务请求中&#xff0c;WEB服务只负责创建主线程来接收外部的HTTPS请求&#xff0c;如果不做任何处理&#xff0c;默认业务逻辑是通过主线程来做的&#xff0c;如果业务…

预训练大语言模型的三种微调技术总结:fine-tuning、parameter-efficient fine-tuning和prompt-tuning

预训练大模型&#xff0c;尤其是大语言模型已经是当前最火热的AI技术。2018年Google发布BERT模型&#xff08;BERT在DataLearner官方模型卡信息&#xff1a;https://www.datalearner.com/ai-models/pretrained-models/BERT &#xff09;的时候&#xff0c;大家还没有意识到本轮…

国际植物命名数据库(International Plant Names Index)

功能介绍 https://www.ipni.org/ 是国际植物命名数据库&#xff08;International Plant Names Index&#xff09;的官方网站。国际植物命名数据库是一个全球性的植物命名和分类资源&#xff0c;旨在提供植物命名信息的权威来源。以下是该网站的一些特点和功能&#xff1a; 植…

wmvcore.dll丢失怎么弄?解决wmvcore.dll丢失问题

wmvcore.dll是Windows Media Player中的一个重要组件&#xff0c;它负责处理视频和音频文件的编码和解码。如果您在使用Windows Media Player或其他媒体播放器时遇到了wmvcore.dll丢失的问题&#xff0c;那么您可能无法播放视频或音频文件。在这种情况下&#xff0c;您可以使用…

干货|接口测试必备技能-常见接口协议解析

【摘要】 服务与服务之间传递数据包&#xff0c;往往会因为不同的应用场景&#xff0c;使用不同的通讯协议进行传递。比如网站的访问&#xff0c;常常会使用 HTTP 协议进行传递&#xff0c;文件传输使用 FTP&#xff0c;邮件传递使用 SMTP。上述的三种类型的协议都处于网络模型…

电流环参数自整定及其原理

前言 电流环参数自整定是通过程序计算电流环PI调节器增益以实现环路响应仅受用户设定PI调节器带宽影响&#xff0c;而和电机本身参数无关的目的。 本文分析电流环参数自整定背后的原理&#xff0c;并通过仿真进行验证。 1、永磁同步电机dq轴数学模型 本文提到的电流环参数自…

【论文总结】Creating a Secure Underlay for the Internet

为互联网创建一个安全的底层 摘要&#xff1a; 对手可以利用跨域路由漏洞拦截通信并破坏关键互联网应用的安全性。与此同时&#xff0c;部署诸如边界网关安全协议&#xff08;BGPsec&#xff09;和下一代网络上的可扩展性、控制和隔离&#xff08;SCION&#xff09;等安全路由…

38 KVM管理设备-管理虚拟机USB

文章目录 38 KVM管理设备-管理虚拟机USB38.1 配置USB控制器38.1.1 概述38.1.2 注意事项38.1.3 配置方法 38.2 配置USB直通设备38.2.1 概述38.2.2 注意事项38.2.3 配置说明38.2.4 配置方法 38 KVM管理设备-管理虚拟机USB 为了方便在虚拟机内部使用USBkey设备、USB海量存储设备等…

蓝桥杯单片机基础模板一:动态数码管显示

蓝桥杯单片机有一些基础模块的写法&#xff0c;他是没有一定的公式模板的。 好比动态数码管扫描显示&#xff0c;原理就是快速地 传输段选和位选。 但因为电路上添加了74HC573芯片&#xff0c;导致了我们移植别处 51单片机的动态扫描代码 会出现诸多问题&#xff0c;比如闪烁…

期末学习总结模板

期末学习总结精选篇1 转眼间研究生的生活已经有一学期了&#xff0c;感觉才参加复试没多久&#xff0c;回头想想&#xff0c;这一年过的真快&#xff0c;因为生病&#xff0c;耽误了很多时间&#xff0c;收获太少&#xff0c;遗憾太多。 本学期的收获&#xff1a; 1、暑假里看了…

Elasticsearch文件存储

分析Elasticsearch Index文件是如何存储的&#xff1f; 主要是想看一下FST文件是以什么粒度创建的&#xff1f; 首先通过kibana找一个索引的shard&#xff0c;此处咱们就以logstash-2023.05.30索引为例 查看下shard分布情况 GET /_cat/shards/logstash-2023.05.30?vindex …

AtCoder Beginner Contest 303——A-E题讲解

蒟蒻来讲题&#xff0c;还望大家喜。若哪有问题&#xff0c;大家尽可提&#xff01; Hello, 大家好哇&#xff01;本初中生蒟蒻讲解一下AtCoder Beginner Contest 303这场比赛的A-E题&#xff01; A - Similar String 原题 Problem Statement Two characters x x x and y…

Python IDLE介绍

目录 IDE&#xff08;集成开发环境&#xff09;是什么 Python IDLE使用方法详解 Python IDLE常用快捷键 IDE&#xff08;集成开发环境&#xff09;是什么 IDE 是 Integrated Development Environment 的缩写&#xff0c;中文称为集成开发环境&#xff0c;用来表示辅助程序员…

一、Fuzzing速成之AFL实战

文章目录 一、Fuzzing基本知识1、什么是Fuzzing?2、Fuzzing运行流程 二、Fuzzing实战1、下载AFL压缩包2、安装AFL3、Fuzzing 一、Fuzzing基本知识 1、什么是Fuzzing? 维基百科将模糊测试定义为&#xff1a;     模糊测试 &#xff08;fuzz testing, fuzzing&#xff09;…

【Python 文本挖掘】零基础也能轻松掌握的学习路线与参考资料

Python文本挖掘是利用Python语言和相关文本挖掘工具对大量文本数据进行分析和挖掘的过程。Python在文本挖掘方面广泛应用于自然语言处理、情感分析、主题建模、关键词提取等领域。 学习Python文本挖掘需要掌握Python编程基础、数据分析和可视化、自然语言处理、机器学习等知识…

Flutter:功能型组件(3)- 拖拽组件、缩放平移组件

拖拽组件 拖拽组件包含 Draggable、LongPressDraggable 和 DragTarget。 Draggable、LongPressDraggable 为可拖拽的组件&#xff0c;LongPressDraggable 继承自Draggable&#xff0c;因此用法和 Draggable 完全一样&#xff0c;唯一的区别就是 LongPressDraggable 触发拖动的…

nginx添加nginx-sticky-module模块步骤

nginx-sticky-module模块是nginx实现负载均衡的一种方案,和ip_hash负载均衡算法会有区别的 ip_hash 根据客户端ip将请求分配到不同的服务器上.sticky 根据服务器个客户端的cookie,客户端再次请求是会带上此cookie,nginx会把有次cookie的请求转发到颁发cookie的服务器上. 安装…