当前位置: 首页 > news >正文

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

目录

一、新建项目

二、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 传输协议:请求协议,响应协议

进程和线程的关系

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • freemarker模板学习笔记
  • 【C#编程技术总结】魔法包唤醒同一局域网设备
  • Unity解析XML开发随机名字生成模块
  • 联想泄露显示本月推出更便宜的Copilot Plus电脑
  • 虚幻引擎VR游戏开发02 | 性能优化设置
  • 不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信
  • vue实现评论滚动效果
  • 网络编程day02(字节序、TCP编程)
  • 600 条最强 Linux 命令总结
  • 都2024年了还不明白Redis持久化?RDB文件、AOF文件、AOF重写
  • 编码器有哪些?
  • sheng的学习笔记-AI-概率图,隐马尔可夫HMM,马尔可夫随机场MRF,条件随机场CRF
  • 如何理解有效值电流?电流的均方根值
  • 并网光伏发电系统对电网电能质量的影响
  • 微信支付开发避坑指南
  • __proto__ 和 prototype的关系
  • bearychat的java client
  • canvas 高仿 Apple Watch 表盘
  • JavaScript实现分页效果
  • PermissionScope Swift4 兼容问题
  • Python连接Oracle
  • text-decoration与color属性
  • 大快搜索数据爬虫技术实例安装教学篇
  • 力扣(LeetCode)965
  • 前端面试之闭包
  • 区块链共识机制优缺点对比都是什么
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 思维导图—你不知道的JavaScript中卷
  • 主流的CSS水平和垂直居中技术大全
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 容器镜像
  • ​如何使用QGIS制作三维建筑
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • #define、const、typedef的差别
  • #单片机(TB6600驱动42步进电机)
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (C++二叉树05) 合并二叉树 二叉搜索树中的搜索 验证二叉搜索树
  • (Forward) Music Player: From UI Proposal to Code
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .jks文件(JAVA KeyStore)
  • .mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
  • .NET CORE 第一节 创建基本的 asp.net core
  • .Net IOC框架入门之一 Unity
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .net反编译的九款神器
  • .NET企业级应用架构设计系列之应用服务器
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • @Slf4j idea标红Cannot resolve symbol ‘log‘