Java NIO 的前生今世 之二 NIO Channel 小结
来源:互联网 发布:c语言中怎么自定义函数 编辑:程序博客网 时间:2024/06/10 12:57
Java NIO Channel
通常来说, 所有的 NIO 的 I/O 操作都是从 Channel 开始的. 一个 channel 类似于一个 stream.java Stream 和 NIO Channel 对比
我们可以在同一个 Channel 中执行读和写操作, 然而同一个 Stream 仅仅支持读或写.
Channel 可以异步地读写, 而 Stream 是阻塞的同步读写.
Channel 总是从 Buffer 中读取数据, 或将数据写入到 Buffer 中.
Channel 类型有:
FileChannel, 文件操作
DatagramChannel, UDP 操作
SocketChannel, TCP 操作
ServerSocketChannel, TCP 操作, 使用在服务器端.这些通道涵盖了 UDP 和 TCP网络 IO以及文件 IO.
基本的 Channel 使用例子:
public static void main( String[] args ) throws Exception{ RandomAccessFile aFile = new RandomAccessFile("/Users/xiongyongshun/settings.xml", "rw"); FileChannel inChannel = aFile.getChannel(); ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf); while (bytesRead != -1) { buf.flip(); while(buf.hasRemaining()){ System.out.print((char) buf.get()); } buf.clear(); bytesRead = inChannel.read(buf); } aFile.close();}
FileChannel
FileChannel 是操作文件的Channel, 我们可以通过 FileChannel 从一个文件中读取数据, 也可以将数据写入到文件中.注意
, FileChannel 不能设置为非阻塞模式.
打开 FileChannel
RandomAccessFile aFile = new RandomAccessFile("test.txt", "rw");FileChannel inChannel = aFile.getChannel();
从 FileChannel 中读取数据
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);}
关闭
当我们对 FileChannel 的操作完成后, 必须将其关闭
channel.close();
设置 position
long pos channel.position();channel.position(pos +123);
文件大小
我们可以通过 channel.size()获取关联到这个 Channel 中的文件的大小. 注意, 这里返回的是文件的大小, 而不是 Channel 中剩余的元素个数.
截断文件
channel.truncate(1024);
将文件的大小截断为1024字节.
强制写入
我们可以强制将缓存的未写入的数据写入到文件中:
channel.force(true);
SocketChannel
SocketChannel 是一个客户端用来进行 TCP 连接的 Channel.创建一个 SocketChannel 的方法有两种:
打开一个 SocketChannel, 然后将其连接到某个服务器中
当一个 ServerSocketChannel 接受到连接请求时, 会返回一个 SocketChannel 对象.
打开 SocketChannel
SocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("http://example.com", 80));
关闭
socketChannel.close();
读取数据
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 为异步模式, 这样我们的 connect, read, write 都是异步的了.
连接
socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("http://example.com", 80));while(! socketChannel.finishConnect() ){ //wait, or do something else... }
在异步模式中, 或许连接还没有建立, connect 方法就返回了, 因此我们需要检查当前是否是连接到了主机, 因此通过一个 while 循环来判断.
读写
在异步模式下, 读写的方式是一样的.在读取时, 因为是异步的, 因此我们必须检查 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();
监听连接
我们可以使用ServerSocketChannel.accept()方法来监听客户端的 TCP 连接请求, accept()方法会阻塞, 直到有连接到来, 当有连接时, 这个方法会返回一个 SocketChannel 对象:
while(true){ SocketChannel socketChannel = serverSocketChannel.accept(); //do something with socketChannel...}
非阻塞模式
在非阻塞模式下, 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... }}
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 一样真正意义上的连接, 而是它会讲 DatagramChannel 锁住, 因此我们仅仅可以从指定的地址中读取或写入数据.
channel.connect(new InetSocketAddress("example.com", 80));
- Java NIO 的前生今世 之二 NIO Channel 小结
- Java NIO 的前生今世 之三 NIO Buffer 详解
- Java NIO 的前生今世 之四 NIO Selector 详解
- Java NIO 的前生今世 之四 NIO Selector 详解
- Netty源码分析之番外篇【Java NIO的前生今世】
- Java NIO 的前生今世 之一 简介
- Java 之NIO(二) - Channel
- 二、Nio之Channel
- Java NIO (二) Channel
- Java NIO之Channel
- Java NIO编程实例之二Channel
- Java NIO的Channel
- Java的NIO之Channel通道
- Java的NIO之Channel通道
- (二)Java NIO Channel
- java NIO教程(二)--Channel
- 解读java nio之channel
- 《JAVA NIO》之Channel类图
- java线程实战:多线程下载(下)
- python 简单任务拆分多线程框架
- Java NIO 的前生今世 之一 简介
- RethinkDB成为Linux基金会的一员
- Python的迭代和递归实现菲波那切数列(Fibonacci sequence)
- Java NIO 的前生今世 之二 NIO Channel 小结
- Project Euler 008 Largest product in a series
- DataBinding入门
- P3601 签到题
- verilog通过中+:与-:解决变量内固定长度数据位的动态选取
- myeclipse的QueryRunner的bug
- Java NIO 的前生今世 之三 NIO Buffer 详解
- 模板与泛型编程之定义模板
- Https的配置