NIO核心知识(区别、Channel、Buffer、Selector、SelectionKey、完整代码案例)
2017-10-27 11:28
639 查看
NIO核心知识
注:图片转载于并发编程网,链接:http://ifeve.com/。
0、IO和NIO的区别
①Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。
②Java IO的各种流是阻塞的。Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。
③Java NIO还提供Selector选择器,使得单线程更容易管理多个连接(多个通道的多个监听事件)。
1、Channel
Channel:翻译为通道,是一个接口,提供通道的实现规范。
作用:一个用于输入/输出操作的连接。通道表示一个实体的开放连接,例如硬件设备、文件、网络套接字或可以使用的程序组件执行一个或多个不同的输入/输出操作,例如读取或写操作。一般来说,通道是安全的,用于多线程访问。
实现类:FileChannel、SocketChannel、ServerSocketChannel、DatagramChannelChannel。
核心方法:
服务端
//打开通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
客户端
//打开通道
SocketChannel socketChannel = SocketChannel.open();
2、Buffer
Buffer:缓存区,是一个抽象类,提供实现不同数据类型缓存区的实现规范。
作用:Buffer用于与NIO通道进行交互,数据是从通道读入到缓冲区,从缓冲区写入通道的。
实现类:ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。
核心方法:
ByteBuffer byteBuffer = ByteBuffer.allocate(buffer_size);
byteBuffer.put(byteArray);
核心属性:
position:当前游标
limit:游标限制
capacity:容量
查看源码
//将position设回0,可以重读Buffer中的所有数据。
//clear方法将缓冲区清空,在重新写缓冲区时调用。
//反转缓冲区,在准备从缓冲区中读取数据时调用flip方法。
3、Selector
Selector是通道监测器,能监测多个通道(Channel)的多个监听事件。
核心方法:
//获取通道监测器
Selector selector = Selector.open();
//监听
select();//阻塞到至少有一个通道在你注册的事件上就绪了。
select(long timeout);//和select()一样,除了最长会阻塞timeout毫秒(参数)。
selectNow();不会阻塞,不管什么通道就绪都立刻返回。
4、SelectionKey
监听事件集合。
核心属性:
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;
核心方法:
//通道注册监听事件到通道监测器
channel.register(selector, SelectionKey.OP_READ);
//如何注册多个监听事件呢?
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//轮询就绪事件
5、完整代码案例
具体步骤:
1、服务端进入监听状态
2、客户端连接服务端,连接成功后向服务端发送消息
3、服务端接受到数据后,向客户端发送消息
服务端:
客户端:
注:图片转载于并发编程网,链接:http://ifeve.com/。
0、IO和NIO的区别
①Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。
②Java IO的各种流是阻塞的。Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。
③Java NIO还提供Selector选择器,使得单线程更容易管理多个连接(多个通道的多个监听事件)。
1、Channel
Channel:翻译为通道,是一个接口,提供通道的实现规范。
作用:一个用于输入/输出操作的连接。通道表示一个实体的开放连接,例如硬件设备、文件、网络套接字或可以使用的程序组件执行一个或多个不同的输入/输出操作,例如读取或写操作。一般来说,通道是安全的,用于多线程访问。
实现类:FileChannel、SocketChannel、ServerSocketChannel、DatagramChannelChannel。
核心方法:
服务端
//打开通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
客户端
//打开通道
SocketChannel socketChannel = SocketChannel.open();
2、Buffer
Buffer:缓存区,是一个抽象类,提供实现不同数据类型缓存区的实现规范。
作用:Buffer用于与NIO通道进行交互,数据是从通道读入到缓冲区,从缓冲区写入通道的。
实现类:ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。
核心方法:
ByteBuffer byteBuffer = ByteBuffer.allocate(buffer_size);
byteBuffer.put(byteArray);
核心属性:
position:当前游标
limit:游标限制
capacity:容量
查看源码
//将position设回0,可以重读Buffer中的所有数据。
public final Buffer rewind() { position = 0; mark = -1; return this; }
//clear方法将缓冲区清空,在重新写缓冲区时调用。
public final Buffer clear() { position = 0; limit = capacity; mark = -1; return this; }
//反转缓冲区,在准备从缓冲区中读取数据时调用flip方法。
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
3、Selector
Selector是通道监测器,能监测多个通道(Channel)的多个监听事件。
核心方法:
//获取通道监测器
Selector selector = Selector.open();
//监听
select();//阻塞到至少有一个通道在你注册的事件上就绪了。
select(long timeout);//和select()一样,除了最长会阻塞timeout毫秒(参数)。
selectNow();不会阻塞,不管什么通道就绪都立刻返回。
4、SelectionKey
监听事件集合。
核心属性:
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;
核心方法:
//通道注册监听事件到通道监测器
channel.register(selector, SelectionKey.OP_READ);
//如何注册多个监听事件呢?
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//轮询就绪事件
while(iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); //略... iterator.remove(); }
5、完整代码案例
具体步骤:
1、服务端进入监听状态
2、客户端连接服务端,连接成功后向服务端发送消息
3、服务端接受到数据后,向客户端发送消息
服务端:
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; /** * @author 周杰 * @time 2017年10月25日 下午2:53:37 */ public class Server { private static final int port = 12345; private static final int buffer_size = 1024; private static final String charsetName = "UTF-8"; private static final String hello_message = "hello client !"; public static void main(String[] args) throws Exception { //获取通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.bind(new InetSocketAddress(port)); //获取通道管理器 Selector selector = Selector.open(); //将通道注册通道管理器的OP_ACCEPT事件 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while(true) { //当有注册事件到达时,方法返回,否则阻塞 selector.select(); Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while(iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); if(!selectionKey.isValid()) { continue; } if(selectionKey.isAcceptable()) { System.out.println("accept a connection..."); ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); }else if(selectionKey.isReadable()) { System.out.println("accept a message..."); SocketChannel sc = (SocketChannel) selectionKey.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(buffer_size); int length = sc.read(byteBuffer); if(length > 0) { String receive_message = new String(byteBuffer.array(), charsetName); System.out.println("server accept : "+receive_message); sc.write(ByteBuffer.wrap(hello_message.getBytes(charsetName))); } } iterator.remove(); } } } }
客户端:
import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; /** * @author 周杰 * @time 2017年10月25日 下午3:10:49 */ public class Client { private static final int port = 12345; private static final int buffer_size = 1024; private static final String charsetName = "UTF-8"; private static final String hello_message = "hello server !"; public static void main(String[] args) throws Exception { //获取通道 SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); //获取通道管理器 Selector selector = Selector.open(); //连接 socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(), port)); //将通道注册通道管理器的OP_CONNECT事件 socketChannel.register(selector, SelectionKey.OP_CONNECT); while(true) { selector.select(); for (SelectionKey key : selector.selectedKeys()) { if(!key.isValid()) { continue; } if(key.isConnectable()) { System.out.println("connect successfully..."); SocketChannel sc = (SocketChannel) key.channel(); if(sc.isConnectionPending()) { sc.finishConnect(); } sc.register(selector, SelectionKey.OP_READ); sc.write(ByteBuffer.wrap(hello_message.getBytes(charsetName))); }else if(key.isReadable()) { System.out.println("accept a message..."); SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(buffer_size); int length = sc.read(byteBuffer); if(length > 0) { String receive_message = new String(byteBuffer.array(), charsetName); System.out.println("client accept : "+receive_message); } } } } } }
相关文章推荐
- Java nio 学习笔记(一) Buffer(缓冲区)与Channel(通道)的相关知识
- java NIO入门简介 Buffer(缓冲区)与Channel(通道)的相关知识
- JAVA基础知识之NIO——Buffer.Channel,Charset,Channel文件锁
- JAVA NIO : Buffer ,Channel, Selector,Pipe
- Java nio 学习笔记(一) Buffer(缓冲区)与Channel(通道)的相关知识
- Java NIO:Buffer、Channel 和 Selector
- NIO+SocketChannel+Buffer+Selector 多路复用
- NIO学习笔记(3)--NIO核心类(Buffer,Channel)
- Java基础知识强化之IO流笔记72:NIO之 NIO核心组件(NIO使用代码示例)
- Java NIO:Buffer、Channel 和 Selector
- JAVA NIO : Buffer ,Channel, Selector
- NIO的Buffer&Channel&Selector
- NIO中Channel、Buffer、Selector详解
- Java nio 学习笔记(一) Buffer(缓冲区)与Channel(通道)的相关知识
- Java NIO SocketChannel+Buffer+Selector 详解(含多人聊天室实例)
- Java nio 学习笔记(一) Buffer(缓冲区)与Channel(通道)的相关知识
- Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
- Netty网络编程二[BIO,线程池BIO,NIO,AIO](代码案例)
- jQuery对象与DOM对象区别 (每都学一点知识,就少些一行代码)
- java.nio.ByteBuffer中flip、rewind、clear方法的区别