Channel (Java NIO)
【正文】netty源码死磕1.3:
Java NIO Channel
1. Java NIO Channel
1.1. Java NIO Channel的特点
和老的OIO相比,通道和NIO流(非阻塞IO)主要有以下几点区别:
(1)OIO流一般来说是单向的(只能读或者写),通道可以读也可以写。
(2)OIO流值读写阻塞的,而通道可以异步读写。
(3)通道总是基于缓冲区Buffer来读写。
1.2. Channel类型
下面列出Java NIO中最重要的集中Channel的实现:
(1)FileChannel
(2)DatagramChannel
(3)SocketChannel
(4)ServerSocketChannel
四种通道的说明如下:
FileChannel用于文件的数据读写。
DatagramChannel用于UDP的数据读写。
SocketChannel用于TCP的数据读写。
ServerSocketChannel允许我们监听TCP链接请求,每个请求会创建会一个SocketChannel。
这个四种通道,涵盖了 UDP 和 TCP网络 IO以及文件 IO的操作。下面从通道的新建、读取、写入、关闭等四个操作,四种通道进行简单的介绍。
1.3. FileChannel
FileChannel 是操作文件的Channel,我们可以通过 FileChannel 从一个文件中读取数据,也可以将数据写入到文件中。
注意,FileChannel 不能设置为非阻塞模式。
操作一:打开 FileChannel通道
RandomAccessFile aFile = new RandomAccessFile("test.txt","rw"); FileChannel inChannel = aFile.getChannel();
操作二:读取数据
ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf);
操作三:写入数据
String newData = "New String to write to file..." + System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while(buf.hasRemaining()) { channel.write(buf); }
操作四:关闭
channel.close();
当我们对 FileChannel 的操作完成后,必须将其关闭。
操作五:强制刷新磁盘
channel.force(true);
FileChannel的force()方法将所有未写入的数据从通道刷新到磁盘中。在你调用该force()方法之前,出于性能原因,操作系统可能会将数据缓存在内存中,因此您不能保证写入通道的数据实际上写入磁盘。
1.4. SocketChannel
有两种Socket通道,一个是客户端的SocketChannel,一个是负责服务器端的Socket通道ServerSocketChannel。SocketChannel与OIO中的Socket类对应,ServerSocketChannel对应于OIO中的ServerSocket类相NIO。
两种Socket通道新增的通道都支持阻塞和非阻塞两种模式。在阻塞模式下的通道的创建、关闭、读写操作如下:
操作一:创建
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1",80));
这个是客户端的创建。当一个服务器端的ServerSocketChannel 接受到连接请求时,也会返回一个 SocketChannel 对象。
操作二:读取
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
如果 read()返回 -1,那么表示连接中断了.
操作三:写入数据
String newData = "New String to write to file..." + System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while(buf.hasRemaining()) { channel.write(buf); }
操作四:关闭
socketChannel.close();
在非阻塞模式,我们可以设置 SocketChannel 为异步模式,这样我们的 connect,read,write 都是异步的了.
操作一:连接
socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("127.0.0.1",80)); while(! socketChannel.finishConnect() ){ //wait,or do something else... }
在异步模式中,或许连接还没有建立,socketChannel.connect 方法就返回了,因此我们不断的自旋,检查当前是否是连接到了主机。
操作二:非阻塞读写
在异步模式下,读写的方式是一样的.
在读取时,因为是异步的,因此我们必须检查 read 的返回值,来判断当前是否读取到了数据.
ServerSocketChannel
ServerSocketChannel 顾名思义,是用在服务器为端的,可以监听客户端的 TCP 连接,例如:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(9999)); while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel... }
操作四:关闭
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.close();
1.4.1. 监听连接
我们可以使用ServerSocketChannel.accept()方法来监听客户端的 TCP 连接请求,accept()方法会阻塞,直到有连接到来,当有连接时,这个方法会返回一个 SocketChannel 对象:
while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel... }
1.4.2. 非阻塞模式
在非阻塞模式下,accept()是非阻塞的,因此如果此时没有连接到来,那么 accept()方法会返回null:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(9999)); serverSocketChannel.configureBlocking(false); while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); if(socketChannel != null){ //do something with socketChannel... } }
1.5. DatagramChannel
DatagramChannel 是用来处理 UDP 连接的.
操作一:打开
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(9999));
操作二:读取数据
ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); channel.receive(buf);
操作三:发送数据
String newData = "New String to write to file..." + System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(48); buf.clear(); buf.put(newData.getBytes()); buf.flip(); int bytesSent = channel.send(buf,new InetSocketAddress("example.com",80));
连接到指定地址
因为 UDP 是非连接的,因此这个的 connect 并不是向 TCP 一样真正意义上的连接,因此我们仅仅可以从指定的地址中读取或写入数据.
channel.connect(new InetSocketAddress("example.com",80));
源码:
代码工程: JavaNioDemo.zip
下载地址:在疯狂创客圈QQ群文件共享。
无编程不创客,无案例不学习。疯狂创客圈,一大波高手正在交流、学习中!
疯狂创客圈 Netty 死磕系列 10多篇深度文章: 【博客园 总入口】 QQ群:104131248
Channel (Java NIO)的更多相关文章
- Java NIO 完全学习笔记(转)
本篇博客依照 Java NIO Tutorial翻译,算是学习 Java NIO 的一个读书笔记.建议大家可以去阅读原文,相信你肯定会受益良多. 1. Java NIO Tutorial Java N ...
- Java NIO Tutorial
Java NIO Tutorial Jakob JenkovLast update: 2014-06-25
- Java NIO系列教程(十一) Java NIO 与 IO
Java NIO系列教程(十一) Java NIO与IO 当学习了 Java NIO 和 IO 的 API 后,一个问题马上涌入脑海: 我应该何时使用 IO,何时使用 NIO 呢?在本文中,我会尽量清 ...
- java NIO系列教程1
ava NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式. Java NIO: Channel ...
- 【Java nio】java nio笔记
缓冲区操作:缓冲区,以及缓冲区如何工作,是所有I/O的基础.所谓“输入/输出”讲的无非就是把数据移出货移进缓冲区.进程执行I/O操作,归纳起来也就是向操作系统发出请求,让它要么把缓冲区里的数据排干,要 ...
- JAVA NIO简介-- Buffer、Channel、Charset 、直接缓冲区、分散和聚集、文件锁
IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. Java标准io回顾 在Java1.4之前的I/O系统中,提供 ...
- [翻译] java NIO Channel
原文地址:http://tutorials.jenkov.com/java-nio/channels.html JAVA NIO channels和流的概念很像,下面是他们的一些区别: 你可以对cha ...
- 转:Java NIO系列教程(七) Socket Channel
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道.可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的某台服务器. ...
- 转:Java NIO系列教程(六) File Channel
Java NIO中的FileChannel是一个连接到文件的通道.可以通过文件通道读写文件. FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下. 打开FileChannel 在使用F ...
随机推荐
- CentOS 7.2安装lepus数据库监控系统
环境说明 系统版本 CentOS 7.2 x86_64 软件版本 lepus 3.7 Lepus是一套开源的数据库监控平台,目前已经支持MySQL.Oracle.SQLServer.MongoDB ...
- Android经常使用UI组件 - Button
button(Button)是Android其中一个经常使用的UI组件.非常小可是在开发中最经常使用到.一般通过与监听器结合使用.从而触发一些特定事件. Button继承了TextView.它的功能就 ...
- Node.js的静态页面想通过jQuery的Ajax函数调用远程服务的措施无效
程序下载:https://files.cnblogs.com/files/xiandedanteng/nodejsMakejqueryAjaxInvalid.rar 在 http://www.cnbl ...
- Codeforces #263 div2 解题报告
比赛链接:http://codeforces.com/contest/462 这次比赛的时候,刚刚注冊的时候非常想好好的做一下,可是网上喝了个小酒之后.也就迷迷糊糊地看了题目,做了几题.一觉醒来发现r ...
- Linux下xargs命令详解及xargs与管道的区别
在工作中经常会接触到xargs命令,特别是在别人写的脚本里面也经常会遇到,但是却很容易与管道搞混淆,本篇会详细讲解到底什么是xargs命令,为什么要用xargs命令以及与管道的区别.为什么要用xarg ...
- kali渗透综合靶机(一)--Lazysysadmin靶机
kali渗透综合靶机(一)--Lazysysadmin靶机 Lazysysadmin靶机百度云下载链接:https://pan.baidu.com/s/1pTg38wf3oWQlKNUaT-s7qQ提 ...
- vs2012_error C2061: 语法错误: 标识符“uint64_t”
加入头文件#include <stdint.h>
- 【HTML5】用脚本控制交互元素details元素的使用
1.源码 <!. Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quo ...
- Ant 风格路径表达式
ANT通配符有三种: 通配符 说明 ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 例子: URL路径 说明 /app/*.x 匹配(Matches)所有在app路径下的 ...
- <转>Windows平台下Makefile学习笔记(一)
本文转自:http://blog.csdn.net/clever101/article/details/8147352 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译平台的问题(发 ...