2.1k 2 分钟

# 简介 该部分之所以为 0,是因为在之后 NIO , AIO 的学习都会大量用到 Socket 的知识,所以为了更好的让读者阅读下去,这里开始对 Socket 做出一点补充。 客户端与服务器连接之后,通过对 Socket 对象的写入和读取进行通信。 连接过程: 服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。 服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。 服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。 Socket...
409 1 分钟

# 简介 前面三种 IO 模型:阻塞式同步,非阻塞式同步,多路复用都是采用的应用主动询问操作系统。也就导致他们都会在执行 read 函数中阻塞住。 异步 IO 采用的是 “订阅 - 通知” 模式:应用程序向操作系统注册 IO 监听,然后继续做自己的事情,当操作系统发生 IO 事件,并且准备好数据后,再主动通知应用程序,触发相应的函数。 异步 IO 也是操作系统进行支持的,Windows 系统提供的异步 IO 技术为 IOCP (I/O Completion Port,I/O 完成端口)。Linux 使用的是 epoll 多路复用 IO 技术模拟异步 IO。 # Java 对异步 IO...
12k 11 分钟

# 简介 关于多路复用(windows 下使用 select)的简单介绍已经在 Unix IO 模型和 NIO 基础详解中大致提到,并给出了代码实现。本文会对相关方法和模型进行详细讲解。 多路复用 IO 技术最适用的是 “高并发” 场景,所谓高并发是指 1 毫秒内至少同时有上千个连接请求准备好。 try(ServerSocket server = new ServerSocket(8888)) { Socket s =...
12k 11 分钟

# 简介 BIO 是阻塞的,如果没有多线程, BIO 就需要一直占用 CPU ,而 NIO 则是非阻塞 IO , NIO 在获取连接或者请求时,即使没有取得连接和数据,也不会阻塞程序。NIO 的服务器实现模式为一个线程可以处理多个请求。 I/O 与 NIO 最重要的区别是数据打包和传输的方式, I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。 面向流的 I/O 一次处理一个字节数据:一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的 I/O 通常相当慢。 #...
2.1k 2 分钟

# 重要概念 阻塞IO 和 非阻塞IO 这两个概念是 程序级别 的。主要描述的是程序请求操作系统 IO 操作后,如果 IO 资源没有准备好,那么程序该如何处理的问题:前者等待;后者继续执行 (并且使用线程一直轮询,直到有 IO 资源准备好了)。 程序级别的差异表现在开发人员如何编写代码来实现不同功能。 同步IO 和 非同步IO 这两个概念是 操作系统级别 的。主要描述的是操作系统在收到程序请求 IO 操作后,如果 IO 资源没有准备好,该如何响应程序的问题:前者不响应,直到 IO 资源准备好以后;后者返回一个标记 (好让程序和自己知道以后的数据往哪里通知),当 IO...
2.5k 2 分钟

# I/O 模型 Unix 包含物种 IO 模型,分别是:阻塞 IO 、非阻塞 IO 、 IO 多路复用、信号驱动 IO 、异步 IO 。和 Java 的 IO 模型有下列对应(不严格) Java-IO 模型 Unix-IO 模型 BIO 阻塞式 IO NIO IO 多路复用 AIO 异步 IO # 内核态与用户态 我们将文件从磁盘加载到内存中。操作系统是怎么做的? 进程陷入内核态,通过系统调用执行文件阅读。 系统调用结束后,返回用户态。 所以 Unix 的五种 IO 模型的不同指出,就是这两个步骤的处理流程不同。 详细可以参考这篇文章:从根上理解用户态与内核态。 # 阻塞式...
9.9k 9 分钟

# IO 常见类 Java 的 I/O 大概可以分成以下几类: 磁盘操作: File 字节操作: InputStream 和 OutputStream 字符操作: Reader 和 Writer 对象操作: Serializable 网络操作: Socket 像 FileInputStream 这样的类都是字节操作的子类,不算入常见类讲解,之后会对这些子类单独开坑。 # 文件流 # File 类 File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。不能访问文件内容本身,需要通过输入输出流进行访问。访问路径可以是绝对 / 相对路径。相对路径是由系统属性 user.dir...
806 1 分钟

# 类结构 # 源码解析 我们已经分析了 InputStream ,这两个很相似,一个 read 对应一个 write ,也是使用了装饰者模式,这里直接给出源码 public abstract class OutputStream implements Closeable, Flushable { // 将指定的字节写入输出流 public abstract void write(int b) throws IOException; // 将指定的 byte 数组的字节全部写入输出流 public void write(byte b[]) throws...
3.8k 3 分钟

# 前言 在阅读本文之前,请先看完上一篇文章中 IO 的类设计使用了装饰者模式。 InputStream 表示输入,是指外界对程序进行数据的输入。它是一个抽象类,即表示所有字节输入流实现类的基类。它的作用就是抽象地表示所有从不同数据源产生输入的类。 # 核心方法 InputStream 的三个 read 是最核心的方法(JDK8),分别是 // 读取下一个字节的数据,如果没有则返回 - 1public abstract int read() public int read(byte b[]) { return read(b, 0, b.length);}...
1.3k 1 分钟

# 前言 为了分类方便和知识的连贯性,这里就将 IO 的部分(关于文件流的操作)也放到网络编程的 Tags 里面。真正的网络编程大概就是从 Socket 那一块开始讲解,接着就是缓冲区,通道以及 NIO 的各种详解。 # 传输方式 分为字节流和字符流: 字节 是个计算机看的, 字符 才是给人看的。 字节流主要是 InputStream 和 OutputStream 派生出来的一些列类。字符流主要 Reader 和 Writer 派生出来的类。 # 字节流和字符流区别 字节流读取单个字节,字符流读取单个字符 (一个字符根据编码的不同,对应的字节也不同,如 UTF-8 编码中文汉字是 3...