Java NIO基本使用介绍
2013-07-28 23:47
363 查看
NIO主要包括Channel,Buffer,Selector三个核心元素组成。
Channel即通道,l和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
Buffer有IntBuffer,CharBuffer,FloatBuffer。。。。。
可以在Selector上注册通道。
Selector所在线程负责处理监听,待所关注的事件到达时,将事件分发给在Selector上注册的channel作异步处理,如下图所示。
调用channel的read()方法,将channel中的数据写入到Buffer中。
调用
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
调用channel的write()方法,将Buffer中的数据写入channel中。
调用
为了理解Buffer的工作原理,需要熟悉它的三个属性:
capacity
position
limit
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。
这里有一个关于capacity,position和limit在读写模式中的说明,详细的解释在插图后面。
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
使用JAVA NIO编写一个客户端与服务端通信的例子。
Server
Client
Client端输入abc后,Server端会将收到的信息返回到Client端,打印"你好,已收到......"
Server端也会打印出Client端发送的消息。
Channel即通道,l和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
Buffer有IntBuffer,CharBuffer,FloatBuffer。。。。。
可以在Selector上注册通道。
Selector所在线程负责处理监听,待所关注的事件到达时,将事件分发给在Selector上注册的channel作异步处理,如下图所示。
Buffer的基本用法
使用Buffer读写数据一般遵循以下四个步骤:调用channel的read()方法,将channel中的数据写入到Buffer中。
调用
flip()方法
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
调用channel的write()方法,将Buffer中的数据写入channel中。
调用
clear()方法或者
compact()方法
为了理解Buffer的工作原理,需要熟悉它的三个属性:
capacity
position
limit
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。
这里有一个关于capacity,position和limit在读写模式中的说明,详细的解释在插图后面。
capacity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。position
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
使用JAVA NIO编写一个客户端与服务端通信的例子。
Server
package com.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class Server { private Selector selector; private ByteBuffer readBuffer = ByteBuffer.allocate(100); public void start() throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.socket().bind(new InetSocketAddress("localhost", 8002)); selector = Selector.open(); ssc.register(selector, SelectionKey.OP_ACCEPT); while (!Thread.currentThread().isInterrupted()) { selector.select(); Set selectedKeys = selector.selectedKeys(); Iterator iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); if (!key.isValid()) { continue; } if (key.isAcceptable()) { accept(key); } else if (key.isReadable()) { read(key); } } iterator.remove(); } } private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); this.readBuffer.clear(); int readNum = 0; try { readNum = socketChannel.read(this.readBuffer); } catch (IOException e) { key.cancel(); socketChannel.close(); return; } if (readNum > 0) { byte[] newBytes = new byte[readNum]; System.arraycopy(readBuffer.array(), 0, newBytes, 0, readNum); String message = new String(newBytes); System.out.println(message); message = "你好,已收到你发的消息:" + message; readBuffer.flip(); readBuffer = ByteBuffer.wrap(message.getBytes()); socketChannel.write(readBuffer); } } private void accept(SelectionKey key) throws IOException { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel clientChanel = ssc.accept(); clientChanel.configureBlocking(false); clientChanel.register(selector, SelectionKey.OP_READ); System.out.println("a new client connected..."); } public static void main(String[] args) throws IOException { new Server().start(); } }
Client
package com.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Scanner; import java.util.Set; public class Client { private void start() throws IOException { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); sc.connect(new InetSocketAddress("localhost", 8002)); Selector selector = Selector.open(); sc.register(selector, SelectionKey.OP_CONNECT ); Scanner scanner = new Scanner(System.in); while (true) { selector.select(); Set selectedKeys = selector.selectedKeys(); Iterator iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); if (key.isConnectable()) { sc.finishConnect(); sc.register(selector, SelectionKey.OP_WRITE); System.out.println("server connected"); break; } else if (key.isWritable()) { System.out.println("please input message"); String message = scanner.nextLine(); ByteBuffer writebufBuffer = ByteBuffer.wrap(message.getBytes()); sc.write(writebufBuffer); sc.register(selector, SelectionKey.OP_READ); }else if(key.isReadable()){ ByteBuffer readBuffer = ByteBuffer.allocate(1024); int readNum = sc.read(readBuffer); byte[] newBytes = new byte[readNum]; System.arraycopy(readBuffer.array(), 0, newBytes, 0, readNum); String message = new String(newBytes); System.out.println(message); sc.register(selector, SelectionKey.OP_WRITE); } } iterator.remove(); } } public static void main(String[] args) throws IOException { new Client().start(); } }
Client端输入abc后,Server端会将收到的信息返回到Client端,打印"你好,已收到......"
Server端也会打印出Client端发送的消息。
相关文章推荐
- Java NIO基本使用
- Java NIO基本使用
- java的泛型基本介绍和使用
- Java互联网架构-MyCat介绍与基本使用
- Java泛型一:基本介绍和使用
- (十六)Core Java 枚举的使用(基本介绍,构造方法枚举,抽象方法枚举) (113)
- java io/nio的使用介绍
- java.nio --Path--Files--基本使用
- java基本数据类型介绍及其使用注意点
- 使用Eclipse-Maven-git做Java开发(4)--关于eclipse的更详细介绍
- AsyncTask的介绍及基本使用方法
- java泛型(一)基本介绍和使用
- java.lang.Void 与 void的比较及使用方法介绍
- java面试要点---ibatiS框架的使用方法介绍---随时更新
- 今日内容介绍 1、自定义类型的定义及使用 2、自定义类的内存图 3、ArrayList集合的基本功能 4、随机点名器案例及库存案例代码优化 ###01引用数据类型_类 * A: 数据类型
- 基于java中BlockingQueue的使用介绍
- Java NIO原理和使用(转载一)
- GRUB基本使用介绍
- Java日志软件Log4j的基本使用教程
- Java数组特点及基本使用技巧