java NIO 同步非阻塞IO
三大组件
- Buffer
buffer 用来存储数据,对8中基本类型有7中buffer 实现,ByteBuffer,ShortBuffer,IntBuffer,CharBuffer,FloatBuffer,DoubleBuffer,LongBuffer,对于boolean ,可以使用其他方式表示,0 表示false 1 表示true
Buffer 的三个要素 ,position(对buffer 进行 get ,put 操作时position 会自动向后移动) , limit(buffer 可以操作的极限范围) ,capctiy(buffer 的容量),三者的关系 position<= limit<=capctiy
- Channel
channel 用来传输数据,传输单位为 buffer,BIO 只能单向传输数据,但是NIO 可以双向传输数据,可以通过 buffer.flip()函数进行切换
常见的Channel
. FileChannel
. UDPChannel: DatagramChannel
. TCPChannel: SocketChannel, ServerSocketChannel
如果不设置,channel 默认时阻塞的,可以通过
channel.configureBlocking(false); 设置为非阻塞
- Selector
多路复用选择器
package server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
public class ServerChannel {
public static void main(String[] args) throws IOException {
//创建serverSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
// 绑定端口
ssc.bind(new InetSocketAddress(8088));
Selector selc = Selector.open();
SelectionKey register = ssc.register(selc, SelectionKey.OP_ACCEPT);
while(true){
selc.select();
Set<SelectionKey> selectionKeys = selc.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if(selectionKey.isAcceptable()){
//接受事件
ServerSocketChannel socketChannel = (ServerSocketChannel) selectionKey.channel();
SocketChannel sc = socketChannel.accept();
sc.configureBlocking(false);
//注册可读可写事件
sc.register(selc,SelectionKey.OP_READ+SelectionKey.OP_WRITE);
}
if(selectionKey.isReadable()){
SocketChannel sc = (SocketChannel) selectionKey.channel();
sc.configureBlocking(false);
sc.register(selc,SelectionKey.OP_READ);
ByteBuffer bb = ByteBuffer.allocate(1024);
sc.read(bb);
System.out.println(new String(bb.array(),0,bb.position()));
//从selector 中移除写事件
sc.register(selc,selectionKey.interestOps()-SelectionKey.OP_READ);
}
if(selectionKey.isWritable()){
SocketChannel sc = (SocketChannel) selectionKey.channel();
sc.configureBlocking(false);
//写出数据
sc.write(ByteBuffer.wrap("hello client".getBytes(StandardCharsets.UTF_8)));
// 从selector 中移除写事件
sc.register(selc,selectionKey.interestOps()-SelectionKey.OP_WRITE);
}
}
iterator.remove();
}
}
}
package client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
public class ClientChannel {
public static void main(String[] args) throws IOException {
//打开 socketChannel
SocketChannel sc = SocketChannel.open();
// 获取连接
sc.connect(new InetSocketAddress("localhost", 8088));
//定义buffer
ByteBuffer bb = ByteBuffer.wrap("hello server".getBytes(StandardCharsets.UTF_8));
//发送数据
sc.write(bb);
ByteBuffer b = ByteBuffer.allocate(1024);
sc.read(b);
byte[] array = b.array();
System.out.println(new String(array,0,b.position()));
//关闭通道
sc.close();
}
}