NIO-Channel

目录

NIO-概览

NIO-Buffer

NIO-Channel

NIO-Channel接口分析

NIO-SocketChannel源码分析

NIO-FileChannel源码分析

NIO-Selector源码分析

NIO-WindowsSelectorImpl源码分析

NIO-EPollSelectorIpml源码分析

前言

本来是想学习Netty的,但是Netty是一个NIO框架,因此在学习netty之前,还是先梳理一下NIO的知识。通过剖析源码理解NIO的设计原理。

本系列文章针对的是JDK1.8.0.161的源码。

什么是Channel

通道(Channel)是对原I/O包中的流的模拟。与文件设备I/O交互的所有数据都必须通过一个Channel对象。

上一节我们提到在NIO中使用缓冲区来存放指定基元的数据,我们可以通过Buffer来读写数据。

将数据写入到硬盘时,我们可以将字节数据写入到缓冲区中;若我们要从硬盘读取数据,则需要通过通道将数据写入到缓冲区,然后再从缓冲区读取数据。

通道类型

根据不同的使用方式,分为不同的通道。比如我们需要网络读写,就需要网络交互的通道。需要文件读写就需要文件交互的通道。

NIO实现了Sctp协议、TCP协议、UDP协议以及文件传输四种通道,同时还实现了Windows平台的异步Socket通道以及异步文件通道。

windows平台的异步I/O是通过重叠I/O和IOCP(I/O完成端口)实现的,想要了解windows异步I/O的知识可以看一下我另一篇文章《Windows内核原理-同步IO与异步IO》

类型 通道
Sctp协议客户端 SctpChannel
Sctp协议多播客户端 SctpMultiChannel
Sctp协议服务端 SctpServerChannel
UDP协议 DatagramChannel
TCP协议同步I/O服务端 ServerSocketChannel
TCP协议同步I/O客户端 ServerChannel
文件读写 FileChannel

对于Windows平台的异步通道

类型 通道
TCP协议异步I/O服务端 WindowsAsynchronousServerSocketChannel
TCP协议异步I/O客户端 WindowsAsynchronousSocketChannel
异步文件读写 WindowsAsynchronousFileChannel

另外NIO还实现了一个单向通讯管道(Pipe)的功能,通过引入SourceChannelSinkChannel实现,底层实际还是Socket通讯。

如何使用

在介绍不同的Channel的实现之前我们先介绍下Channel如何使用。

ServerSocketChannel

以TCP协议为例,我们进行网络收发的时候,首先需要创建一个ServerSocketChannel用于监听端口。

//创建一个服务端socket通道用于接收连接
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//绑定监听地址
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
//等待连接
SocketChannel socketChannel = serverSocketChannel.accept();

我们监听了8080端口。若没有连接时,线程会阻塞在accept

当有收到新的连接创建时,会获取到SocketChannel,此时我们需要创建一个Buffer用来从Channel中读取数据。

ByteBuffer buf = ByteBuffer.allocate(1024);
//数据将写入到buffer中
int length = socketChannel.read(buf);

数据写入到我们的Buffer中,我们就需要将他们读出来

buf.flip();  //转化为可读模式
byte[] data = new byte[length];
buf.get(data);

将数据从Buffer写入到Channel时

buf.clear();
byte[] resp = {'O','K'};
buf.put(resp);
buf.flip();//转换为读模式
socketChannel.write(buf);

这里为了方便直接使用原来的Buffer。

SocketChannel

作为客户端我们需要创建一个SocketChannel。

SocketChannel.open();
client.connect(new InetSocketAddress("127.0.0.1", 6060));

发送HELLO给服务端

ByteBuffer buffer = ByteBuffer.allocate(10);
byte[] data = {'H', 'E', 'L', 'L', 'O'};
buffer.put(data);
buffer.flip();//转换为读模式
client.write(buffer);

阻塞等待读取数据

buffer.clear();
client.read(buffer);
buffer.flip();//转换为读模式

处理完成,需要关闭释放连接

//关闭客户端输入流
client.socket().shutdownInput();
//关闭客户端输出流
client.socket().shutdownOutput();
//关闭客户端socket时会关闭客户端channel
client.socket().close();
//关闭客户端channel,会同时关闭输入和输出流。
client.close();

关闭输出流会发送FIN包,若输入流未关闭仍然可以继续接收数据,这就是TCP的半连接。若处理完最后需要确保channel关闭。

FileChannel

FileChannel只能被FileInputStream、FileOutputStream、RandomAccessFile创建

RandomAccessFile

使用RandomAccessFile创建FileChannel

//第一个参数时文件名,第二个参数是读写方式
RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt","rw");
FileChannel channel = randomAccessFile.getChannel();

FileInputStream

使用RandomAccessFile创建FileChannel

FileInputStream  inputStream = new FileInputStream("1.txt");
channel = inputStream.getChannel();

inputStream获取的FileChannel只能读

FileOutputStream

使用RandomAccessFile创建FileChannel


FileOutputStream outputStream = new FileOutputStream("1.txt");
channel = outputStream.getChannel();

inputStream获取的FileChannel只能写

关闭FileChannel

关闭FileChannel的方法和关闭SocketChannel方法一样。

//关闭channel时会关闭文件
channel.close();
//关闭文件时会关闭channel
randomAccessFile.close();
//关闭文件流时会关闭channel
inputStream.close();
//关闭文件流时会关闭channel
inputStream.close();

总结

由于源码解析的篇幅较长,因此将channel源码单独分出来讲解。

相关文献

  1. SCTP协议详解
  2. 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!
  3. Java NIO系列教程



微信扫一扫二维码关注订阅号杰哥技术分享

出处:https://www.cnblogs.com/Jack-Blog/p/12015516.html

作者:杰哥很忙

本文使用「CC BY 4.0」创作共享协议。欢迎转载,请在明显位置给出出处及链接。

最新文章

  1. 从sum()求和引发的思考
  2. A 标签的背景
  3. thinkphp基于角色的权限控制详解
  4. libc abi.dylib: terminate_handler unexpectedly threw an exception
  5. adb devices指令实例讲解
  6. DomFlags - 给 DOM 添加书签,方便调试
  7. Ubuntu 14.10 下SSH执行远程命令
  8. NeHe OpenGL教程 第十课:3D世界
  9. 1.项目开发-->Memcached之ASP.NET实现
  10. IPAD之分割视图 SplitViewController
  11. jquerymobile知识点:button与a
  12. spring 定时任务的 执行时间设置规则
  13. Oracle EBS-SQL (SYS-17):查询一张报表在哪个职责下面.sql
  14. Microsoft office PPT 2007 保存时速度慢(整理自网上)
  15. Struts2学习笔记NO.1------结合Hibernate完成查询商品类别简单案例(工具IDEA)
  16. LeetCode_p150_逆波兰表达式计算/后缀表达式计算
  17. Spring在项目中需要的配置
  18. 1.numpy的用法
  19. 弃 Java 而使用 Kotlin 的你后悔了吗?| kotlin将会是最好的开发语言
  20. Unity3d 协程(IEnumerator)范例

热门文章

  1. 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
  2. formdata,ajax提交数据
  3. NOIP的模板--考前复习
  4. git 生成密匙时遇到报错 :Too many arguments.
  5. Linux | 性能分析系列学习 (1)
  6. 转载]OK6410之tftp下载内核,nfs挂载文件系统全过程详解[转]
  7. 模拟实现IoC容器
  8. T-SQL Part X: UNION, EXCEPT and INTERSECT
  9. 使用 Casbin 作为 ThinkPHP 的权限控制中间件
  10. nyoj 457-大小写互换