Java NIO & AIO编程

  • NIO 编程
  • AIO 编程

NIO 编程

NIO : Non - Blocking I/O:非阻塞I/O

  1. 一个线程,可以管理多个线程。
  2. 避免同步I/O通讯差的特点。

主要类:
Buffer:缓冲区;
Channel:全双工数据通道;
Selector:多路选择器。

实现过程:

  1. 通过多路选择器轮询,获得有事件操作的集合;
  2. 通过SocketChannel读取数据;
  3. 在Buffer中实现对数据的操作。

例子:

  1. 在服务端,创建Selector,并且配置服务器通道信息,注册Selector。
  2. 轮询获取有数据变化的通道。
  3. 对每个通道中的数据内容进行读写操作。
package 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.Set;import java.util.Iterator;public class NIOServer {public static void main(String[] args) {int port = 8003;Selector selector = null;ServerSocketChannel serverChannel = null;try {selector = Selector.open();  //选择器打开serverChannel = ServerSocketChannel.open();//服务端口打开serverChannel.configureBlocking(false);//设置为非阻塞模式serverChannel.socket().bind(new InetSocketAddress(port), 1024);//绑定端口serverChannel.register(selector, SelectionKey.OP_ACCEPT);//注册选择器System.out.println("服务器在端口8001等待!");}catch(IOException e) {e.printStackTrace();}while(true) {try {selector.select(1000);//获取有数据动向的通道,轮询。Set<SelectionKey> selectionKey = selector.selectedKeys();Iterator<SelectionKey> it = selectionKey.iterator();SelectionKey key = null;while(it.hasNext()) {key = it.next();it.remove();try {//对每个通道对数据,进行专门处理。handleInput(selector, key);}catch(Exception e) {if(key != null) {key.cancel();if(key.channel() != null)key.channel().close();}}}}catch(Exception e){e.printStackTrace();}try {Thread.sleep(500);}catch(InterruptedException e) {e.printStackTrace();}}}public static void handleInput(Selector selector, SelectionKey key) throws IOException {if(key.isValid()) {//处理新接入的信息请求if(key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);}if(key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer readBuffer = ByteBuffer.allocate(1024);int readBytes = sc.read(readBuffer);//在通道上调用read方法,将数值放到readBuffer中if(readBytes > 0) {// 将缓存字节数组的指针设置为数组的开始序列即数组下标0。//  这样就可以从buffer开头,对该buffer进行遍历(读取)了。 readBuffer.flip();//反转缓冲区byte[] bytes = new byte[readBuffer.remaining()];readBuffer.get(bytes);String request = new String(bytes, "UTF-8");System.out.println("Client said:" + request);String response = request + "666";doWrite(sc, response);}  else if (readBytes < 0) {// 对端链路关闭 key.cancel();sc.close();}}}}public static void doWrite(SocketChannel sc, String response) throws IOException {if(response !=null && response.trim().length() > 0) {byte[] bytes = response.getBytes();ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);writeBuffer.put(bytes);writeBuffer.flip();sc.write(writeBuffer);}}
}

客户端代码:
即时客户端只有一个,还是可以设置一下。多路选择。路数就一路。

  1. 创建Selector, SocketChannel。配置信息并注册。
  2. 轮询各个通道,对每个有数据的通道进行读写处理。
package NIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.UUID;
import java.util.Iterator;public class NIOClient {public static void main(String[] args) {Selector selector = null;SocketChannel socketChannel = null;String host = "127.0.0.1";int port = 8003;try {selector = Selector.open();socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);if(socketChannel.connect(new InetSocketAddress(host, port))) {socketChannel.register(selector, SelectionKey.OP_READ);doWrite(socketChannel);}else {socketChannel.register(selector, SelectionKey.OP_CONNECT);}}catch(IOException e) {e.printStackTrace();}while(true) {try {selector.select(1000);Set<SelectionKey> selectionKey = selector.selectedKeys();Iterator<SelectionKey> it = selectionKey.iterator();SelectionKey key;while(it.hasNext()) {key = it.next();it.remove();try {//处理每一个keyhandleKey(selector, key);}catch(Exception e) {if(key != null) {key.cancel();if(key.channel() != null){key.channel().close();}}}}}catch(Exception e) {e.printStackTrace();}}}public static void doWrite(SocketChannel sc) throws IOException {byte[] str = UUID.randomUUID().toString().getBytes();ByteBuffer writeBuffer = ByteBuffer.allocate(str.length);writeBuffer.put(str);writeBuffer.flip();sc.write(writeBuffer);}public static void handleKey(Selector selector, SelectionKey key) throws ClosedChannelException, IOException {if(key.isValid()) {SocketChannel sc = (SocketChannel) key.channel();if(key.isConnectable()) {if(sc.finishConnect()) sc.register(selector, SelectionKey.OP_READ);}if(key.isReadable()) {ByteBuffer readBuffer = ByteBuffer.allocate(1024);int readBytes = sc.read(readBuffer);if(readBytes > 0) {readBuffer.flip();byte[] bytes = new byte[readBuffer.remaining()];readBuffer.get(bytes);String body = new String(bytes, "UTF-8");System.out.println("Server said: " + body);}else if(readBytes < 0) {key.cancel();sc.close();}else;}try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}doWrite(sc);}}
}

AIO 编程

AIO:Asynchronous I/O。异步I/O。
只需要设置后续操作,当相关条件满足时,自动执行。
采用回调的方式进行数据读写处理。

主要类:
AsynchronousServerSocketChannel :服务器接收请求通道;
方法:
bind绑定端口,accept,接收客户端请求。
AsynchronousSocketChannel:通讯通道。
方法:
read:从通道中读数据,write:写数据到通道中。
CompletionHandler:异步处理类;
方法:
completed:操作完成调用;failed;操作失败调用。

例子:
服务端:

  1. 创建通道server,绑定端口8001;
  2. 当accept方法完成,执行调用异步类中当completed方法;失败则执行failed方法。
  3. 当channel.read方法完成,执行其中的completed方法。失败则执行failed方法。
package AIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;public class AIOServer {public static void main(String[] args) throws IOException {AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();server.bind(new InetSocketAddress("localhost", 8001));System.out.println("服务器在8001端口等待!");server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>(){@Overridepublic void completed(AsynchronousSocketChannel channel, Object attachment) {server.accept(null, this);//持续接受新的客户需求ByteBuffer buffer = ByteBuffer.allocate(1024);channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>(){@Overridepublic void completed(Integer result, ByteBuffer attachment) {attachment.flip(); //反转此Buffer CharBuffer charBuffer = CharBuffer.allocate(1024);CharsetDecoder decoder = Charset.defaultCharset().newDecoder();decoder.decode(attachment,charBuffer,false);charBuffer.flip();String data = new String(charBuffer.array(),0, charBuffer.limit());System.out.println("client said: " + data);channel.write(ByteBuffer.wrap((data + " 666").getBytes())); //返回结果给客户端try{channel.close();}catch (Exception e){e.printStackTrace();}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("read error "+exc.getMessage());                       }});}@Overridepublic void failed(Throwable exc, Object attachment) {System.out.print("failed: " + exc.getMessage());                }});    while(true) {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

客户端:

  1. 创建通讯通道,并连接服务器地址。
  2. 当连接成功,执行异步处理类中的completed方法,失败执行failed方法。
  3. 当channel.write: 向通道中写数据,成功,执行其中的completed方法,失败执行failed方法。
  4. 当channel.read:读取通道中的数据,成功,执行其中completed方法,失败执行对应的failed方法。
package AIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.UUID;public class AIOClient {public static void main(String[] args) {try {AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();channel.connect(new InetSocketAddress("localhost", 8001), null, new CompletionHandler<Void, Void>(){@Overridepublic void completed(Void result, Void attachment) {String str = UUID.randomUUID().toString();channel.write(ByteBuffer.wrap(str.getBytes()), null, new CompletionHandler<Integer, Object>(){@Overridepublic void completed(Integer result, Object attachment) {try {System.out.println("准备读取空间!");ByteBuffer byteBuffer = ByteBuffer.allocate(1024);channel.read(byteBuffer, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {attachment.flip(); //反转此Buffer CharBuffer charBuffer = CharBuffer.allocate(1024);CharsetDecoder decoder = Charset.defaultCharset().newDecoder();decoder.decode(attachment,charBuffer,false);charBuffer.flip();String data = new String(charBuffer.array(),0, charBuffer.limit());System.out.println("server said: " + data);try{channel.close();}catch (Exception e){e.printStackTrace();}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("read error " + exc.getMessage());                                            }});channel.close();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void failed(Throwable exc, Object attachment) {System.out.println("write error");}});         }@Overridepublic void failed(Throwable exc, Void attachment) {System.out.println("error");                   }});try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}} catch (IOException e) {e.printStackTrace();}  }
}

Java NIO AIO编程相关推荐

  1. Java NIO Socket编程实例

    各I/O模型优缺点 BIO通信模型 BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程处理新接入的客户端链路,一个线程只能处理一个客户端连接 线程池I/O编程 假如所有可用 ...

  2. 你对Java网络编程了解的如何?Java NIO 网络编程 | Netty前期知识(二)

    本文主要讲解NIO的简介.NIO和传统阻塞I/O有什么区别.NIO模型和传统I/O模型之间的对比.以及围绕NIO的三大组件来讲解,理论代码相结合. 很喜欢一句话:"沉下去,再浮上来" ...

  3. Java NIO网络编程之群聊系统

    概述 对ServerSocketChannel.SocketChannel.SelectionKey有一定的理解和了解对应API. NIO非阻塞网络编程相关关系梳理: 以下概念: ServerSock ...

  4. 二、Java NIO Channel

    一.Java NIO 网络编程 二.Java NIO Channel 三.Java NIO Buffer 四.Java NIO Selector 五.Java NIO 扩展组件 一.Channel 概 ...

  5. Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  6. (转载)Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    转载请注明出处:http://blog.csdn.net/anxpp/article/details/51512200,谢谢! 本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解 ...

  7. Java IO编程全解(五)——AIO编程

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7794151.html 前面讲到:Java IO编程全解(四)--NIO编程 NIO2.0引入了新的异步通道的 ...

  8. JAVA 中BIO,NIO,AIO的理解

    [转自]http://qindongliang.iteye.com/blog/2018539 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? ...

  9. Java之IO,BIO,NIO,AIO

    2019独角兽企业重金招聘Python工程师标准>>> 参考文献一 IO基础知识回顾 java的核心库java.io提供了全面的IO接口.包括:文件读写.标准设备输出等.Java中I ...

最新文章

  1. mysql 中的脏读与幻读_一文带你理解脏读,幻读,不可重复读与mysql的锁,事务隔离机制...
  2. 欧司朗台灯的灯泡容易坏是怎么回事
  3. Kafka学习笔记-Java简单操作
  4. CoreJava 笔记总结-第五章 继承
  5. MySQL高级知识(二)——Join查询
  6. jsf集成spring_Spring JSF集成
  7. easypoi 大数据 百万_scrapy 解决爬虫IP代理池,百万大数据轻松爬取。
  8. linux 占用缓存前10_MySQL基于linux的内存分析
  9. 蛮牛第2季- Unity2d游戏开发经典教程
  10. Linux - Kafka集群搭建
  11. PHP获取今日农历日期
  12. win7旗舰版6l打印机咋安驱动_打印机安装不了,教您解决打印机驱动安装不了
  13. 通过Windows批处理脚本批量修改DNS
  14. 屏蔽百度搜索结果页的推送广告
  15. HEVC学习笔记(二)整体介绍
  16. 目标检测--RFBNet训练自己制作数据集出现loss=nan问题的解决方法
  17. 宝钢大型高炉控制中心介绍
  18. 王者荣耀坦克位思路和上分必读知识
  19. 流量依赖症患者国际漫游指南
  20. Binary Tree Upside Down LC解题记录

热门文章

  1. JustOJ1500: 蛇行矩阵
  2. random模块 时间模块 sys模块 os模块 json模块 pickle模块
  3. Python学习笔记015——汉字编码
  4. 基于ThinkPHP3.23的简单ajax登陆案例
  5. 微信填写服务器配置 php操作方法
  6. 用C#生成随机中文汉字验证码
  7. PHP函数调用的新的用法
  8. 牛客网华为机试考试java_牛客网——华为机试(题17:坐标移动)(Java)
  9. C语言课后习题(59)
  10. java中thread实例_Java多线程并发执行demo代码实例