Socket学习记录

本次学习Socket的编程开发,该技术在一些通讯软件,比如说微信,QQ等有广泛应用。

网络结构

这些都是计算机网络中的内容,我们在这里简单回顾一下:

在这里插入图片描述

UDP(User Datagram Protocol):用户数据报协议;TCP(Transmission ControlProtocol):传输控制协议。

在这里插入图片描述

TCP协议
特点:面向连接、可靠通信。
TCP的最终目的:要保证在不可靠的信道上实现可靠的传输。
TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接。

在这里插入图片描述

四次握手是为了确保收发数据都已完成。

在这里插入图片描述

我们首先了解一下关于获取主机地址的相关方法:

		//获取本机IP地址对象的地址
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost.getHostName());
        System.out.println(localHost.getHostAddress());
        //获取指定IP域名的IP地址对象
        InetAddress ip = InetAddress.getByName("www.baidu.com");
        System.out.println(ip.getHostName());//输出ip主机名称
        System.out.println(ip.getHostAddress());//输出指定域名的ip地址
        //判断6秒内能否与百度联通,相当于ping
        System.out.println(ip.isReachable(6000));

在这里插入图片描述

UDP通信开发

随后我们进行客户端与服务端的数据发送与接收:
首先是客户端的定义:

		//创建客户端对象,这里可以选择使用无参构造,当然也可以指定端口进行有参构造,在不指定端口时系统会默认分配
        DatagramSocket socket = new DatagramSocket();
        //创建数据包封装对象,存储数据信息
//        public DatagramPacket(byte buf[], int offset, int length,
//        InetAddress address, int port) {
//            setData(buf, offset, length);
//            setAddress(address);
//            setPort(port);
//        }
        byte[] bytes = "客户端消息:我是鹏翔".getBytes();
        //客户端发送的数据包,需要指明接收的服务端的IP地址以及端口
        DatagramPacket packet =
                new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),8888);
        //发送数据包
        socket.send(packet);
        System.out.println("客户端数据发送完毕");
        socket.close();

服务端的开发设计

		System.out.println("服务端启动");
        //创建一个服务端对象,并指定端口
        DatagramSocket socket = new DatagramSocket(8888);
        //定义所能够接收的数据的大小
        byte[] buffer = new byte[1024*64];
        //服务器接受的数据包
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        //接收数据
        socket.receive(packet);
        int length = packet.getLength();
        String string = new String(packet.getData(), 0, length);//发送多少数据则接收多少数据
        System.out.println(string);
        socket.close();

至此,我们的客户端与服务端便开发完成了,在实验中,我们需要先启动服务端,再启动客户端。

在这里插入图片描述
至此,完成客户端与服务端的消息发送与接收。

UTP通信多发多收

但这只是完成了一次消息的发送与接收,而在实际情况中我们往往需要进行多发多收,那么该如何实现呢?
客户端设计:

public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建一个服务端对象,并指定端口
        DatagramSocket socket = new DatagramSocket(8888);
        //定义所能够接收的数据的大小
        byte[] buffer = new byte[1024*64];
        //服务器接受的数据包
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
        while(true){
            socket.receive(packet);
            int length = packet.getLength();
            String string = new String(packet.getData(), 0, length);
            System.out.println(string);
            System.out.println("--------------------------");
        }
    }

客户端设计:

public static void main(String[] args) throws IOException {
        //创建客户端对象
        DatagramSocket socket = new DatagramSocket();
        Scanner scanner=new Scanner(System.in);
        while(true){
            System.out.println("请说:");
            String msg = scanner.nextLine();
            if ("exit".equals(msg)) {
                System.out.println("客户端数据发送完毕");
                socket.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            //客户端发送的数据包,需要指明接收的服务端的IP地址以及端口
            DatagramPacket packet =
                    new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),8888);
            //发送数据包
            socket.send(packet);
        }

此外,服务器是否能够接收多个客户端发送的消息呢,当然可以,只需要将客户端程序设置为允许多开即可。

在这里插入图片描述

TCP通信开发

在这里插入图片描述

public ServerSocket(int port) 为服务端程序注册端口

public Socket accept()方法:阻塞等待客户端的连接请求,一旦与某个客户端成功连接,则返回服务端这边的Socket对象。
客户端设计实现

		Socket socket = new Socket("127.0.0.1",8088);
        //从socket中获取一个字节输出流,用于给服务端发送
        OutputStream outputStream = socket.getOutputStream();
        //原本的字节输出流并不好用,将其封装为高级的数据输出流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        //开始写数据
        dataOutputStream.writeUTF("我爱你!");
        dataOutputStream.close();
        socket.close();

服务端设计实现

		System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(8088);
        //调用accept方法,等待客户端的连接请求
        Socket accept = serverSocket.accept();
        //从socket的通信管道中得到一个字节输入流
        InputStream inputStream = accept.getInputStream();
        //将原始的字节输入流包装成高级的数据输入流
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        //使用数据输入流读取客户端发送的数据
        String string = dataInputStream.readUTF();//通信很严格,要保持一致
        System.out.println(string);
        System.out.println(accept.getInetAddress());//输出发送客户端的IP地址
        dataInputStream.close();
        serverSocket.close();

在这里插入图片描述

在这里插入图片描述

同样的,我们只是完成一条消息的发送与接收,那么该如何实现数据的多发多收呢?

TCP通信多发多收

其实实现与UDP时的完全相同,只需要一个循环即可。
全选要加入循环的语句,按住Ctrl+Alt+T

多发多收服务端设计:

public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(8088);
        //调用accept方法,等待客户端的连接请求
        Socket accept = serverSocket.accept();
        //从socket的通信管道中得到一个字节输入流
        InputStream inputStream = accept.getInputStream();
        //将原始的字节输入流包装成高级的数据输入流
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        //使用数据输入流读取客户端发送的数据
        while (true) {
            String string = dataInputStream.readUTF();//通信很严格,要保持一致
            System.out.println(string);
            System.out.println(accept.getInetAddress());//输出发送客户端的IP地址
        }
    }

多发多收客户端设计:

 public static void main(String[] args) throws IOException {
        //创建Socket对象,并同时请求服务端程序的连接,声明服务器的IP与端口号
        Socket socket = new Socket("127.0.0.1",8088);
        //从socket中获取一个字节输出流,用于给服务端发送
        OutputStream outputStream = socket.getOutputStream();
        //原本的字节输出流并不好用,将其封装为高级的数据输出流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        //开始写数据
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入内容:");
            String string = scanner.nextLine();
            if ("exit".equals(string)) {
                dataOutputStream.close();
                socket.close();
                System.out.println("退出成功!");
                break;
            }
            dataOutputStream.writeUTF(string);
            dataOutputStream.flush();//将数据刷新出去,防止数据还留在内存中
        }
    }

在这里插入图片描述

同时需要注意,TCP作为可靠连接,一旦服务端挂掉了,那么就会抛出异常

在这里插入图片描述

我们可以通过捕获抛出的异常,来判断是否客户端退出。

public class Servers {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(8088);
        //调用accept方法,等待客户端的连接请求
        Socket accept = serverSocket.accept();
        //从socket的通信管道中得到一个字节输入流
        InputStream inputStream = accept.getInputStream();
        //将原始的字节输入流包装成高级的数据输入流
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        //使用数据输入流读取客户端发送的数据
        while (true) {
            try {
                String string = dataInputStream.readUTF();//通信很严格,要保持一致
                System.out.println(string);
            } catch (IOException e) {
                System.out.println(accept.getInetAddress()+"客户端退出了!");//输出发送客户端的IP地址
                dataInputStream.close();
                serverSocket.close();
                break;
            }
        }

    }
}

在这里插入图片描述

TCP通信聊天室

如何实现一个服务器与多个客户端通信呢?现在的肯定是不行的,因为我们在判断客户端关闭后也将服务端关闭了,事实上,此时服务端只能和一个客户端建立可靠连接,归根接地,是因为在建立连接后,服务端一直在等待某一个客户端发送的消息,这就导致会停留在那,从而无法与其他客户端建立连接。怎么办呢?可以使用多线程来解决。

在这里插入图片描述
改进后的服务端:

package IPAddress.TCP;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerMany {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(8088);
        //调用accept方法,等待客户端的连接请求
        Socket accept = null;
        while (true) {
            accept = serverSocket.accept();
            new ServerReadThread(accept).start();
        }
    }
}

多开线程实现服务端接收数据

package IPAddress.TCP;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServerReadThread extends Thread{
    private Socket socket;
    public ServerReadThread(Socket accept) {
        this.socket=accept;
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            //将原始的字节输入流包装成高级的数据输入流
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            System.out.println(socket.getInetAddress()+"客户端上线了!");//输出发送客户端的IP地址
            //使用数据输入流读取客户端发送的数据
            while (true) {
                try {
                    String string = dataInputStream.readUTF();//通信很严格,要保持一致
                    System.out.println(string);
                } catch (IOException e) {
                	System.out.println(socket.getInetAddress()+"客户端下线了!");
                    dataInputStream.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("服务异常!" + socket.getInetAddress() + "连接中断!");
        }
    }
}

在这里插入图片描述

最后,我们可以通过一个聊天室的案例来简单检验一下成果:

在这里插入图片描述
首先我们需要在服务端定义一个集合,用于保存连接的socket,同时由主线程负责创建socket连接,一旦有新的客户端开启,则开启一个新的子线程,用于该客户端与服务端之间的通信:

public class Server {
    public static List<Socket> sockets=new ArrayList<>();
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(8088);
        //调用accept方法,等待客户端的连接请求
        Socket accept = null;
        while (true) {
            accept = serverSocket.accept();
            sockets.add(accept);
            new ServerReadThread(accept).start();
        }
    }
}

在服务端的子线程中,负责将接收的信息输出,并将接收的信息转发给其他客户端(端口转发)

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

public class ServerReadThread extends Thread{
    private Socket socket;
    public ServerReadThread(Socket accept) {
        this.socket=accept;
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            //将原始的字节输入流包装成高级的数据输入流
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            System.out.println(socket.getInetAddress()+"客户端上线了哟!");//输出发送客户端的IP地址
            //使用数据输入流读取客户端发送的数据
            while (true) {
                try {
                    String string = dataInputStream.readUTF();//通信很严格,要保持一致
                    System.out.println(string);
                    sendMsg(string);
                } catch (IOException e) {
                    System.out.println(socket.getInetAddress()+"客户端下线了!");
                    Server.sockets.remove(socket);
                    dataInputStream.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("服务异常!" + socket.getInetAddress() + "连接中断!");
        }
    }

    private void sendMsg(String string) throws IOException {
        //发送给所有Socket管道去接收
        System.out.println("转发数据");
        for (Socket online:Server.sockets) {
            OutputStream outputStream = online.getOutputStream();
            DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
            dataOutputStream.writeUTF(string);
            dataOutputStream.flush();
        }
    }
}

在客户端设计中,除了原本的输入数据发送信息外,还要开启一个线程用于接收服务器转发的数据:

public class Clients {
    public static void main(String[] args) throws IOException {
        //创建Socket对象,并同时请求服务端程序的连接,声明服务器的IP与端口号
        Socket socket = new Socket("127.0.0.1",8088);
        new ClientReadThread(socket).start();
        //从socket中获取一个字节输出流,用于给服务端发送
        OutputStream outputStream = socket.getOutputStream();
        //原本的字节输出流并不好用,将其封装为高级的数据输出流
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        //开始写数据
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入内容:");
            String string = scanner.nextLine();
            if ("exit".equals(string)) {
                dataOutputStream.close();
                socket.close();
                System.out.println("退出成功!");
                break;
            }
            dataOutputStream.writeUTF(string);
            dataOutputStream.flush();//将数据刷新出去,防止数据还留在内存中
        }
    }
}

客户端接收转发信息的线程设计如下:

public class ClientReadThread extends Thread{
    private Socket socket;
    public ClientReadThread(Socket accept) {
        this.socket=accept;
    }
    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            //将原始的字节输入流包装成高级的数据输入流
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            //使用数据输入流读取客户端发送的数据
            while (true) {
                try {
                    String string = dataInputStream.readUTF();//通信很严格,要保持一致
                    System.out.println(string);
                } catch (IOException e) {
                    System.out.println("自己客户端下线了!");
                    dataInputStream.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("服务异常!" + socket.getInetAddress() + "连接中断!");
        }
    }
}

在这里插入图片描述

BS架构通信开发

首先了解一下BS架构的基本原理:

在这里插入图片描述
BS架构下,我们并不需要开发客户端程序。只需要开发服务端即可

public class Server {
    public static List<Socket> sockets=new ArrayList<>();
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(9090);
        while (true) {
            Socket accept = serverSocket.accept();
            System.out.println("子线程启动");
            sockets.add(accept);
            new ServerReadThread(accept).start();
        }
    }
}

随后进行服务端子进程的设计,用于向浏览器响应一段文字,注意,要想向浏览器响应内容,就需要遵循固定的HTTP协议规定,即符合下面的要求:

在这里插入图片描述
服务端子线程设计如下:

public class ServerReadThread extends Thread{
    private Socket socket;
    public ServerReadThread(Socket accept) {
        this.socket=accept;
    }

    @Override
    public void run() {
        try {
            System.out.println("上线访问了");
            OutputStream outputStream = socket.getOutputStream();
            //将原始的字节输出流包装成高级的打印流
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println("HTTP/1.1 200 OK");
            printStream.println("Content-Type:text/html;charset=UTF-8");
            printStream.println();
            printStream.println("<div style='color:red;font-size:40px;text-align:center'>服务端响应</div>");
            printStream.close();
            socket.close();
        } catch (IOException e) {
            System.out.println("服务异常!" + socket.getInetAddress() + "连接中断!");
        }
    }
}

前面的BS架构设计中,每当浏览器发起一次访问,就会创建一个线程,然而,当我们的网站访问量十分大时,即面对一些高并发情况,就会出现宕机现象。对于这种情况,可以通过线程池来进行优化。

在这里插入图片描述

在主线程中设计一个线程池来控制线程数量

public class Server {
    public static List<Socket> sockets=new ArrayList<>();
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        //创建ServerSocket对象,并指明端口号,方便接收客户端数据
        ServerSocket serverSocket = new ServerSocket(9090);
        //通过线程池来控制执行线程的数量与任务队列数量
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                16 * 2, 16 * 2,
                0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(8),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        while (true) {
            Socket accept = serverSocket.accept();
            System.out.println("子线程启动");
            threadPoolExecutor.execute(new ServerReadRunnable(accept));
        }
    }
}

将原本的线程改造为任务。

public class ServerReadRunnable implements Runnable{
    private Socket socket;
    public ServerReadRunnable(Socket accept) {
        this.socket=accept;
    }

    @Override
    public void run() {
        try {
            System.out.println("上线访问了");
            OutputStream outputStream = socket.getOutputStream();
            //将原始的字节输出流包装成高级的打印流
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println("HTTP/1.1 200 OK");
            printStream.println("Content-Type:text/html;charset=UTF-8");
            printStream.println();
            printStream.println("<div style='color:red;font-size:40px;text-align:center'>服务端响应</div>");
            printStream.close();
            socket.close();
        } catch (IOException e) {
            System.out.println("服务异常!" + socket.getInetAddress() + "连接中断!");
        }
    }
}

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

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

相关文章

厂家自定义 Android Ant编译流程源码分析

0、Ant安装 Windows下安装Ant&#xff1a; ant 官网可下载 http://ant.apache.org ant 环境配置&#xff1a; 解压ant的包到本地目录。 在环境变量中设置ANT_HOME&#xff0c;值为你的安装目录。 把ANT_HOME/bin加到你系统环境的path。 Ubuntu下安装Ant&#xff1a; sudo apt…

【数据结构】树和二叉树基本概念和性质

目录 前言1、树的概念1.1 树的基本概念1.2 树的主要概念1.3 树的表示1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2. 二叉树概念及结构2.1 概念2.2 特殊的二叉树2.3 二叉树的性质 3. 二叉树性质相关选择题练习4. 答案和解析5. 总结 前言 本章带来数…

2024年03月 Scratch 图形化(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共18题,共50分) 第1题 运行程序后,角色一定不会说出的数字是?( ) A:2 B:4 C:6 D:8 答案:A 程序中随机数的取值最小为 2,最大为 20 ,那么随机数加上 2 之后的结果的最小值为 4 ,最大值为 22 。所…

单目标问题的烟花优化算法求解matlab仿真,对比PSO和GA

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 单目标问题的FW烟花优化算法求解matlab仿真,对比PSO和GA。最后将FW&#xff0c;GA&#xff0c;PSO三种优化算法的优化收敛曲线进行对比。 2.测试软件版本以及运行…

【Android项目】“追茶到底”项目介绍

没有多的介绍&#xff0c;这里只是展示我的项目效果&#xff0c;后面会给出具体的代码实现。 一、用户模块 1、注册&#xff08;第一次登陆的话需要先注册账号&#xff09; 2、登陆&#xff08;具有记住最近登录用户功能&#xff09; 二、点单模块 1、展示饮品列表 2、双向联动…

T型槽地轨承载力是如何连接整个制造过程的强力桥梁(北重公司设计)

T型槽地轨承载力的定义和计算 T型槽地轨是一种用于工业设备运输和装配的关键组件。它由世界上各行各业的生产商广泛采用&#xff0c;其有效的承载力使其成为连接整个制造过程的强力桥梁。本文将介绍T型槽地轨的承载力以及相关的设计要点和应用。 承载力的定义和计算 承载力是…

【前沿模型解析】一致性模型CM(一)| 离散时间模型到连续时间模型数学推导

文章目录 1 离散时间模型2 连续时间模型 得到 SDE 随机微分方程2.1 从离散模型到SDE的推理步骤 3 补充&#xff1a;泰勒展开近似 1 − β i \sqrt{1-\beta_i} 1−βi​ ​ CM模型非常重要 引出了LCM等一系列重要工作 CM潜在性模型的数学公式推导并不好理解 一步一步&#xf…

微信个人号开发api接口-视频号矩阵接口-VIdeosApi

友情链接&#xff1a;VIdeosApi 获取用户主页 接口地址&#xff1a; http://api.videosapi.com/finder/v2/api/finder/userPage 入参 { "appId": "{{appid}}", "lastBuffer": "", "toUserName": "v2_060000231003b2…

WP Rocket插件下载:加速您的WordPress网站,提升用户体验

在互联网速度决定用户体验的今天&#xff0c;一个快速加载的网站对于吸引和保留访问者至关重要。WP Rocket插件&#xff0c;作为一款专为WordPress设计的高性能缓存插件&#xff0c;提供了一套完整的解决方案&#xff0c;帮助您优化网站性能&#xff0c;提升用户体验。 [WP Ro…

51单片机入门:蜂鸣器

蜂鸣器介绍 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号。 蜂鸣器的种类 1、从结构上&#xff1a;压电式蜂鸣器和电磁式蜂鸣器。 压电式蜂鸣器&#xff1a;通过压电陶瓷的压电效应原理工作的。当加有交变电压时&#xf…

【分布式 | 第五篇】何为分布式?分布式锁?和微服务关系?

文章目录 5.何为分布式&#xff1f;分布式锁&#xff1f;和微服务关系&#xff1f;5.1何为分布式&#xff1f;5.1.1定义5.1.2例子5.1.3优缺点&#xff08;1&#xff09;优点&#xff08;2&#xff09;缺点 5.2何为分布式锁&#xff1f;5.2.1定义5.2.2必要性 5.3区分分布式和微服…

Unity 性能优化之光照优化(七)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、测试目的一、实时光源是什么&#xff1f;二、开始测试1.场景中只有一个光照的数值情况2.添加4个点光源后4.结果 总结 前言 实时光源数量越多&#x…

C++类细节,面试题02

文章目录 2. 虚函数vs纯虚函数3. 重写vs重载vs隐藏3.1. 为什么C可以重载&#xff1f; 4. 类变量vs实例变量5. 类方法及其特点6. 空类vs空结构体6.1. 八个默认函数&#xff1a;6.2. 为什么空类占用1字节 7. const作用7.1 指针常量vs常量指针vs常量指针常量 8. 接口vs抽象类9. 浅…

CSS选择器、字体文本属性、三大特性、盒子模型等

目录 导入css简介HTML的局限性CSS-网页美化CSS语法规范CSS代码风格 选择器基础选择器复合选择器 CSS字体属性字体系列font-family字体大小font-size字体粗细font-weight文字样式font-style字体复合属性font CSS文本属性文本颜色color对齐文本text-align装饰文本text-decoration…

Hive数据模型

Hive数据模型 1. 表&#xff08;Table&#xff09;&#xff1a; 表是数据库中的基本组成单位&#xff0c;用于存储数据。它由一系列的行和列组成&#xff0c;每行代表一个记录&#xff0c;每列代表一种属性或字段。创建表时&#xff0c;你需要定义列的数据类型、约束和索引等信…

水电站LCU屏技术参数,应用案例解析

项目咨询请点击&#xff1a;设备自动化技术商务咨询 水电站LCU屏简介&#xff1a; 水电站LCU屏一般布置在水电站设备附近&#xff0c;对电站设备的运行工况进行实时监视和控制&#xff0c;是电站计算机监控系统的较底层控制部分。水电站一般会配置一个公用LCU屏柜&#xff0c;…

linux学习笔记——硬盘原理以及linux中的sector与block

在计算机硬盘中&#xff0c;最小的存储单位叫做扇区sector&#xff0c;0.5kb&#xff0c;多个连续扇区组合在一起形成了块block&#xff0c;最小的块包含8个扇区&#xff0c;4kb 我们可以在linux中印证 创建一个新的文件2.txt&#xff0c;查看文件大小为0k 在文件中添加字符后…

2022——蓝桥杯十三届2022国赛大学B组真题

问题分析 看到这个问题的同学很容易想到用十层循环暴力计算&#xff0c;反正是道填空题&#xff0c;一直算总能算得出来的&#xff0c;还有些同学可能觉得十层循环太恐怖了&#xff0c;写成回溯更简洁一点。像下面这样 #include <bits/stdc.h> using namespace std; in…

大厂Java面试题:MyBatis是如何进行分页的?分页插件的实现原理是什么?

大家好&#xff0c;我是王有志。 今天给大家带来的是一道来自京东的关于 MyBatis 实现分页功能的面试题&#xff1a;MyBatis是如何进行分页的&#xff1f;分页插件的实现原理是什么&#xff1f;通常&#xff0c;分页的方式可以分为两种&#xff1a; 逻辑&#xff08;内存&…

PON网络和HFC网络

目录 1.概念 2.分类 3.重点 1.概念 PON PON是一种典型的无源光纤网络&#xff0c;是一种点到多点的无源光纤接入技术。 是指 (光配线网中) 不含有任何电子器件及电子电源&#xff0c;ODN全部由光分路器 (Splitter) 等无源器件组成&#xff0c;不需要贵重的有源电子设备。一个…