在NIO中有几个核心对象需要掌握:缓冲区(Buffer)、通道(Channel)、选择器(Selector)。
缓冲区Buffer
缓冲区实际上是一个容器对象,更直接的说,其实就是一个数组,在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流I/O系统中,所有数据都是直接写入或者直接将数据读取到Stream对象中。
首先建立服务器端,代码如下
<span style="font-size:14px;"> </span><span style="font-size:18px;">ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("server start on port:" + port);</span>
先建立通道,然后得到一个ServerSocket并绑定到一个端口上,Selector selector,这个就是nio中的选择器,
<span style="font-size:18px;">serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);</span>
这句话的意思就是在我们的通道上注册选取器选择可接受的请求(SelectionKey.OP_ACCEPT)
我们还需要一个方法去轮询我们的请求
<span style="font-size:18px;">while (true) {
try {
int readyChannels = selector.select();
if(readyChannels == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if(key.isValid())
handle(key);
keys.remove(key);
};
} catch (Exception e) {
e.printStackTrace();
break;
}
</span><span style="font-size:14px;">
}</span>
首先选择器去找到所有的请求,我们通过SelectionKey可以去处理这些请求
我们如何处理呢??
private void handle(SelectionKey selectionKey) throws Exception {
ServerSocketChannel server = null;
SocketChannel client = null;
if (selectionKey.isAcceptable()) {
server = (ServerSocketChannel) selectionKey.channel();
client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
client = (SocketChannel) selectionKey.channel();
if (client.isConnected()) {
try {
rBuffer.clear();
while (client.read(rBuffer) > 0) {
rBuffer.flip();
}
byte[] save = rBuffer.array();
ByteArrayInputStream bi = new ByteArrayInputStream(save);
ObjectInputStream oi = new ObjectInputStream(bi);
bi.close();
oi.close();
if (client.isConnected()) {
client.register(selector, SelectionKey.OP_READ);
} else {
System.out.println("2连接断开aaaaaa");
}
} catch (IOException e) {
client.close();
System.out.println("2异常无连接aaaaaa");
}
} else {
System.out.println("连接断开=======");
}
}
}
读数据需要单独的线程,如:
while (true) {
while (scanner.hasNext()) {
mess = scanner.next();
try {
server.server_fasong(mess);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ok啦,这样既可以读又可以写啦