【学习笔记】手写 Tomcat -- 预备知识

news2024/12/26 13:42:26

目录

一、新建项目

二、IO流

1. 什么是IO流?

2. IO的流向说明图解

3. IO 流的分类

4. 字节流

输出流

字节输出流的细节

输入流

字节输入流的细节

5. 练习

6. 字符流

输入流

字符流读取的细节

字符输入流原理解析

字符输出流原理解析

三、网络编程

1. UDP通信程序

UDP 发送数据

UDP 接收数据

2. TCP 通信程序

TCP发送端

TCP 服务器端

3. 解读代码

Socket 套接字

传输数据的类型

accept 方法

read 方法

返回的 -1 

作业

1. 实现在线聊天室

2. 预习


一、新建项目

二、IO流

1. 什么是IO流?

I 是 Input,O 是Output,也就是输入输出流。

当我们操作数据时,以内存为基准,把数据读取到内存中是输入,把数据从内存写入到硬盘是输出

2. IO的流向说明图解

图片来自哔哩哔哩黑马程序员

3. IO 流的分类

根据数据的流向可以分为:输入流和输出流

根据数据的类型可以分为:字节流和字符流

操作文件类型

字节流:以字节为单位,可以操作所有文件类型

字符流:以字符为单位,只能输入输出纯文本文件

4. 字节流

输出流
//1. 创建 FileOutputStream 对象,指定写入的文件路径。

FileOutputStream fos = new FileOutputStream("文件路径");


//2. 将字符串转换为字节数组并写入文件。

fos.write("hello".getBytes());


//3. 关闭输出流

fos.close();

 

字节输出流的细节

1.创建字节输出流的对象

  1. 参数是字符串表示的路径或者File文件对象都是可以的
  2. 如果文件不存在,就会创建一个新的文件,不过需要父级路径是正确的
  3. 如果文件已经存在,会覆盖原文件

2.写数据

是根据字节对应的ASCII码表

3.关闭数据流

追加

在创建字节输出流的对象的时候,第二个参数是打开追加

输入流
//1. 创建 FileInputStream 对象,指定读取的文件路径。

FileInputStream fis = new FileInputStream("文件路径");


//每次只会读取一个字节,读取出来的是int型,需要转成Char类型

System.out.println((char)fis.read());


//释放资源

fis.close();

字节输入流的细节

1. 创建对象

        如果指定的路径文件不存在,会字节报错

2. 读取内容

        一次只会读取一个字节,读取的是ASCII码表对应的数值

        当读取指针指到末尾没有内容了,会返回-1

3. 释放资源

5. 练习

拷贝文件

当使用一个字节一个字节来读取数据,再写入数据的方式,速度比较慢

所以,可以定义一个数组,一次读取尽量把数组装满,一次写入整个数组的数量

FileInputStream fis = new FileInputStream(要读取的文件路径);
FileOutputStream fos = new FileOutputStream(要写入的文件路径);

//创建一个数组,用来一次读取多少字节
byte [] buf = new byte[1024*1024*10];

int b;
while ((b = fis.read(buf)) != -1) {
    fos.write(buf, 0, b);            //第一个参数表示将buf数组里的数据写入到文件里
}                                    //第二个参数是从 0 索引开始,写入的字节数是 b
fis.close();
fos.close();

 

解读代码

fis.read(buf)用于从输入流中读取数据到缓冲区buf,返回值b表示实际读取到的数据字节数。当读取到的数据为-1时,表示输入流已经到达末尾,循环结束。

fos.write(buf, 0, b)则用于将缓冲区中的数据写入到输出流中,写入的字节数为b。

6. 字符流

输入流
//创建字符流对象
FileReader fr = new FileReader("要读取的文件路径");
int ch;
//字符流的底层也是字节流,默认也是一次读取一个字节
while ( (ch = fr.read() )  != -1){
    System.out.print( (char) ch);        //读取出来后会自动解码然后转成十进制
}                                        //所以再转成字符就可以了
fr.close();
字符流读取的细节
  •         字符流的底层也是字节流,默认也是按照一个字节一个字节读取的
  •         遇到中文就会一次读取多个字节,这样可以避免乱码,编码不同,一次读取的字节也不同
  •         在读取之后,底层会自动解码然后转成十进制数,然后把十进制数返回
  •         返回的十进制数也是表示字符集上的数值, 如果需要看到汉字,那么就需要再转成字符就行了

字符输入流原理解析

1. 创建字符输入流对象

底层会关联文件,并且在内存里创建一个byte数组作为缓冲区,长度为8192字节的数组

2. 读取数据

        底层:        1.判断缓冲区有没有数据可以读取

                           2.缓冲区没有数据:从文件里读取数据到缓冲区,尽量把缓冲区装满

                                如果文件里没有数据了,返回-1

                           3.缓冲区有数据:从缓冲区获取数据。

                                空参的read方法:一次读取一个字节,遇到中文一次读取多个字节(根据字符集),把字节解码后并且转成十进制数字返回

                                有参的read方法:把读取字节,解码,转成文字合并了,然后把文字放在数组里

字符输出流原理解析

创建字符输出流的对象的时候,在内存会创建一个缓冲区

有三种情况会把缓冲区的数据写入到文件里

  1. 当缓冲区存放满了的时候
  2. 手动刷新,flush刷新之后还可以继续写数据
  3. 释放资源

要学习 Tomcat ,就需要先了解什么是网络编程

创建两个类 一个作为客户端,一个作为服务器端

三、网络编程

1. UDP通信程序

  • Java中的UDP通信
    • UDP协议是一种不可靠的无连接的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
    • Java提供了DatagramSocket类作为基于UDP协议的Socket
  • 构造方法

方法名

说明

DatagramSocket()

创建数据报套接字并将其绑定到本机地址上的任何可用端口

DatagramPacket(byte[] buf,int len,InetAddress add,int port)

创建数据包,发送长度为len的数据包到指定主机的指定端口

  • 相关方法

方法名

说明

void send(DatagramPacket p)

发送数据报包

void close()

关闭数据报套接字

void receive(DatagramPacket p)

从此套接字接受数据报包

UDP 发送数据
//创建发送端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket();

//创建数据,并把数据打包
//构造一个数据包,发送长度为 length 的数据包到指定IP上的指定端口号。
byte[] bys = "你好".getBytes();

DatagramPacket dp = new DatagramPacket(bys,bys.length,InetAddress.getByName("127.0.0.1"),8888);

//调用DatagramSocket对象的 send 方法发送数据
ds.send(dp);

//关闭通信通道
ds.close();

UDP 接收数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

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

        // 创建一个DatagramSocket实例,绑定到8888端口,用于接收UDP数据包。
        DatagramSocket ds = new DatagramSocket(8888);

        // 创建一个大小为1024字节的字节数组,用于存储接收到的数据。
        byte[] bytes = new byte[1024];
        // 该实例用于接收UDP数据包。
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length);

        // receive方法接收来自任何发送者的数据包,并将其存储在dp中。
        // 这个方法是阻塞的,直到接收到一个数据包。
        ds.receive(dp);

        // 获取接收到的数据包中的数据部分和长度。
        byte[] data = dp.getData();
        int length = dp.getLength();

        // 将接收到的字节数据转换为字符串并打印。
        // 字符串的起始位置是0,长度是数据包的实际长度。
        // 这样可以确保只打印接收到的有效数据部分。
        System.out.println(new String(data,0, length));

        // 释放资源
        ds.close();

    }
}

测试

2. TCP 通信程序

  • Java中的TCP通信
    • Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
    • Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
TCP发送端
import java.io.IOException;
import java.io.OutputStream;
import java.net.*;

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

        //1.创建Socket对象
        //细节:在创建对象的同时会连接服务端
        //      如果连接不上,代码会报错
        Socket socket = new Socket("127.0.0.1",8080);

        //2.可以从连接通道中获取输出流
        OutputStream os = socket.getOutputStream();
        //写出数据
        os.write("hello".getBytes());

        //3.释放资源
        os.close();
        socket.close();
    }
}
TCP 服务器端
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

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

        // 创建一个ServerSocket对象,监听8888端口,等待客户端连接
        ServerSocket ss = new ServerSocket(8080);

        // 调用accept()方法阻塞等待,直到有客户端连接到服务器,返回一个Socket对象用于与该客户端通信
        Socket socket = ss.accept();

        System.out.println("客户端连接成功");

        // 获取Socket对象的输入流,用于读取客户端发送的数据
        InputStream is = socket.getInputStream();

        // 定义一个整型变量b,用于存储读取到的字节
        int b;

        // 循环读取输入流中的数据,read()方法返回-1表示流已结束
        while ((b = is.read()) != -1){
            // 将读取到的字节转换为字符并输出
            System.out.print((char)b);
        }

        // 关闭与客户端的连接
        socket.close();
        // 关闭连接通道
        ss.close();
    }
}

3. 解读代码

TCP 服务器端

  1. accept 方法是阻塞的,作用就是等待客户端连接
  2. 客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接
  3. 针对客户端来讲,是往外写的,所以是输出流,针对服务器来讲,是往里读的,所以是输入流
  4. read 方法也是阻塞的
  5. 客户端在关流的时候,还多了一个往服务器写结束标记的动作,结束标记 -1 
  6. 最后一步断开连接,通过四次挥手协议保证连接终止

Socket 套接字

Socket 套接字,作用就是用来实现网络上不同主机的应用程序进行双向通信。

套接字包括 IP 地址和端口号两个部分。

Socket 被用于应用层和传输层之间的通信。

Java 提供的 Socket 的类的核心功能就是 建立连接,发送数据,接收数据

Socket(InetAddress address,int port)         建立连接

getoutputStram()                                        发送数据

getInputStream()                                        接收数据

传输数据的类型

在网络中,数据传输的都是字节 byte,然后把字节放到字节数组里发送,这就是为什么在发送数据前要把数据转成字节

accept 方法

accept 方法用于接收来自客户端的连接请求。这个方法是阻塞的,也就是它会一直等待,直到有一个新的客户端连接才会继续往下执行

read 方法

read 方法是从当前建立的连接通道中读取字节,一次读取一个字节,所以使用循环读取数据。

read 方法也是阻塞的,这意味着它会一直等待直到有足够的数据可读,或者直到连接关闭。

那数据读取完了怎么结束等待呢?判断数据是否读取完,如果读取完,就停止循环

返回的 -1 

当客户端主动关闭连接后会发送一个结束标志,服务端的 read 方法就会返回 -1 ,表示客户端关闭了连接

当读完数据时,read 方法会返回 -1 ,表示数据读取完毕

作业

1. 实现在线聊天室

可以使用TCP建立连接

张三发送:你好

李四发送:你好呀

2. 预习

网络通信三要素:IP、端口、协议

TCP、UDP,它们之间的区别是什么?

三次握手、四次挥手

HTTP 传输协议:请求协议,响应协议

进程和线程的关系

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

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

相关文章

NVIDIA GH200 超级芯片:重塑超算性能与AI基准的革新之作

Nvidia 正在将其 GH200 芯片应用于欧洲超级计算机,研究人员正在着手研究这些系统并发布带有性能基准的研究论文。 在第一篇论文《理解紧密耦合异构系统中的数据移动:以 Grace Hopper 超级芯片为例》中,研究人员对 GH200 的各种应用进行了基准…

vue2关闭eslint

vue2关闭eslint 1、找到项目build目录下的webpack.base.conf.js文件 2、注释createLintingRule()里面的内容(只注释里面的内容) 3、重启项目即可

自己动手实现mybatis的底层框架(不用动态代理直接用执行器、用动态代理自己实现。图文分析!)

目录 一.原生mybits框架图分析 自己实现Mybatis框架的分析 两种框架操作数据库的方法: 二.搭建开发环境 1.先创建一个maven项目 2.加入依赖(mysql dom4j junit lombok) 三.mybatis框架的设计思路 具体实现过程 3.1实现任务阶段 1- 完成读取配置文件&#x…

基于 TiDB 资源管控 + TiCDC 实现多业务融合容灾测试

导读 随着金融行业的不断发展,多个业务系统的整合成为了趋势,分布式数据库的应用也愈发广泛。为了应对多业务融合带来的复杂性,金融机构需要在保障各业务系统高效运行的同时,确保 IT 系统的高可用性和稳定性。本文将介绍 TiDB 如…

多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现DBO-BP蜣螂算法优化BP神经网络…

如何选择合适的数据报表工具?

在企业的日常运营中,数据报表如同企业的“仪表盘”,为管理者提供了关键的业务信息。无论是销售数据、财务状况还是生产进度,都需要通过数据报表进行清晰的呈现。同时,随着企业对数据可视化的需求不断增加,数据看板和数…

Numba最近邻插值(CPU+ GPU + Z轴切块 + XYZ轴切块 + 多线程)

文章目录 最近邻插值(加速方法)(1)scipy.ndimage.zoom(2)Numba-CPU加速(3)Numba-GPU加速(4)Numba-CPU加速(Z轴切块)(5&…

docker运行springboot项目

博客中若有侵权或者错误的地方,请及时告知,感谢。 1. 背景 在开发中使用k8s部署,日常也只是写个dockerFile, 没有想过整个部署流程是怎样的。今天我们自己部署docker镜像。 2.实战 2.1 建立springboot项目 (1) JAVA项目打包 (解决no mai…

Minio笔记-Centos搭建Minio

下载 Minio wget https://dl.min.io/server/minio/release/linux-amd64/minio 赋予执行权限 chmod x minio 创建存储目录 mkdir /data 运行 Minio ./minio server /data 默认端口为9000 访问 Minio 控制台:在浏览器中输入 http://your-server-ip:9000 默认…

FPGA Prototyping vs Emulation

FPGA Prototyping vs. Emulation One way to visualize the difference between Prototyping and Emulation is with a “spider chart” (named for its resemblance to a spider’s web). The Prototyping vs. Emulation spider chart below highlights the differences bet…

斐纳切数列考试题

计算机二级考试有一道题 result [] a,b0,1 while a<100:print(a,end,) a, b b, ab # 0,1,1,2,3,5,8,13,21,34,55,89,

LLM - 理解 多模态大语言模型 (MLLM) 的发展与相关技术 (二)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142063880 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 多模态…

idea 日志打印乱码

在这里插入图片描述 配置中改为一致

算法篇_RGB图像数据压缩与解压(单片机使用)

文章目录 一、前言二、算法选型2.1 Run-Length Encoding (RLE)2.2 Differential Pulse-Code Modulation (DPCM) 三、采用RLE算法实现图像压缩四、哈夫曼编码实现压缩和解压4.1 哈夫曼编码压缩自定义数据与还原4.2 哈夫曼编码压缩完成图像的压缩和还原 书接上回&#xff08;上一…

Java重修笔记 第五十一天 泛型

泛型 1. 对加入集合的数据类型进行约束&#xff0c;提高了安全性 2. 不用做专门的数据类型转换&#xff0c;就可以直接使用从集合取出来的对象&#xff0c;效率高 在类定义中使用泛型 1. 在类名后面跟上 <泛型列表> 表示该类所使用的使用泛型&#xff0c;具体是什么…

nginx 使用篇 配置

一、介绍 1.介绍 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;同时也是一个邮件代理服务器&#xff0c;它以稳定性、丰富的功能集、简单的配置文件和低系统资源消耗而闻名。 作为一个轻量级的服务器&#xff0c;Nginx在处理高并发连接方面表现出色&#xff0c;能够支…

怎么修复松下相机死机视频只有0字节(0KB)的MDT文件【实测可修复】

死机后视频文件大小仅为0字节 松下S5相机录像死机&#xff0c;关机重新开机后有一个视频文件变成MDT&#xff0c;大小为0KB&#xff0c;录了30多分钟&#xff0c;本应为MOV格式的视频。0字节文件可以修复吗&#xff1f;怎么修复0字节的MDT文件为视频&#xff1f; 数据提取与视…

认知杂谈55

今天分享 有人说的一段争议性的话 I I I I 内容摘要 这篇内容主要有以下要点&#xff1a;首先&#xff0c;人际交往有难度&#xff0c;要让大家都喜欢很难&#xff0c;需学习沟通技巧&#xff0c;可通过看书、关注抖音博主、参加培训班及看罗翔视频片段来提升。其次&#xf…

【C++11 ——— 类的新功能】

C11 ——— 类的新功能 类的新功能默认成员函数类成员变量初始化强制生成默认函数的关键字default禁止生成默认函数的关键字delete 类的新功能 默认成员函数 原来C类中&#xff0c;有6个默认成员函数&#xff1a; 构造函数析构函数拷贝构造函数拷贝赋值重载取地址重载const …

代码随想录刷题day27丨455.分发饼干 ,376. 摆动序列 ,53. 最大子序和

代码随想录刷题day27丨455.分发饼干 ,376. 摆动序列 ,53. 最大子序和 1.贪心算法理论基础 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 这么说有点抽象&#xff0c;来举一个例子&#xff1a; 例如&#xff0c;有一堆钞票&#xff0c;你可以拿走十张&a…