前言介绍
在Java中,提供了一些关于使用IO的API,可以供开发者来读写外部数据和文件,我们称这些API为Java IO。IO是Java中比较重要知识点,且比较难学习的知识点。并且随着Java的发展为提供更好的数据传输性能,目前有三种IO共存;分别是BIO、NIO和AIO。
Java BIO[Blocking I/O] | 同步阻塞I/O模式
BIO 全称Block-IO 是一种同步且阻塞的通信模式。是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。
Java NIO[New I/O] | 同步非阻塞模式
-
Java NIO,全程 Non-Block IO ,是Java SE 1.4版以后,针对网络传输效能优化的新功能。是一种非阻塞同步的通信模式。
-
NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
-
面向流的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。
-
面向块的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O - 缺少一些面向流的 I/O 所具有的优雅性和简单性。
Java AIO[Asynchronous I/O] | 异步非阻塞I/O模型
Java AIO,全程 Asynchronous IO,是异步非阻塞的IO。是一种非阻塞异步的通信模式。在NIO的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。
如下我们将分别对三种IO进行案例演示,通过对三种的IO的认知来方便学习后续的Netty知识。
开发环境
1、jdk1.8【jdk1.7及以上,AIO需要1.7】
2、NetAssist 网络调试助手[获取:关注公众号:bugstack虫洞栈 | 回复;NetAssist+邮箱]
代码示例
1itstack-demo-netty-1-00 2└── src 3 ├── main 4 │ └── java 5 │ └── org.itstack.demo.netty 6 │ ├── aio 7 │ │ ├── client 8 │ │ │ ├── AioClient.java 9 │ │ │ └── AioClientHandler.java 10 │ │ ├── server 11 │ │ │ ├── AioServer.java 12 │ │ │ ├── AioServerChannelInitializer.java 13 │ │ │ └── AioServerHandler.java 14 │ │ ├── ChannelAdapter.java 15 │ │ ├── ChannelHandler.java 16 │ │ └── ChannelInitializer.java 17 │ ├── bio 18 │ │ ├── client 19 │ │ │ ├── BioClient.java 20 │ │ │ └── BioClientHandler.java 21 │ │ ├── server 22 │ │ │ ├── BioServer.java 23 │ │ │ └── BioServerHandler.java 24 │ │ ├── ChannelAdapter.java 25 │ │ └── ChannelHandler.java 26 │ └── nio 27 │ ├── client 28 │ │ ├── NioClient.java 29 │ │ └── NioClientHandler.java 30 │ ├── server 31 │ │ ├── NioServer.java 32 │ │ └── NioServerHandler.java 33 │ ├── ChannelAdapter.java 34 │ └── ChannelHandler.java 35 └── test 36 └── java 37 └── org.itstack.demo.test 38 └── ApiTest.java
重点代码块讲解,完整代码,关注公众号:bugstack虫洞栈 | 回复Netty源码获取
AIO案例代码
aio/client/AioClient.java | 客户端
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class AioClient { 7 8 public static void main(String[] args) throws Exception { 9 AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open(); 10 Future<Void> future = socketChannel.connect(new InetSocketAddress("192.168.1.116", 7397)); 11 System.out.println("itstack-demo-netty client start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 12 future.get(); 13 socketChannel.read(ByteBuffer.allocate(1024), null, new AioClientHandler(socketChannel, Charset.forName("GBK"))); 14 Thread.sleep(100000); 15 } 16 17}
aio/client/AioClientHandler.java | 客户端消息处理器
1** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class AioClientHandler extends ChannelAdapter { 7 8 public AioClientHandler(AsynchronousSocketChannel channel, Charset charset) { 9 super(channel, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 try { 15 System.out.println("微信公众号:bugstack虫洞栈 | 链接报告信息:" + ctx.channel().getRemoteAddress()); 16 //通知客户端链接建立成功 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 } 21 22 @Override 23 public void channelInactive(ChannelHandler ctx) { 24 } 25 26 @Override 27 public void channelRead(ChannelHandler ctx, Object msg) { 28 System.out.println("微信公众号:bugstack虫洞栈 | 服务端收到:" + new Date() + " " + msg + "\r\n"); 29 ctx.writeAndFlush("客户端信息处理Success!\r\n"); 30 } 31 32}
aio/server/AioServer.java | 服务端
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class AioServer extends Thread { 7 8 private AsynchronousServerSocketChannel serverSocketChannel; 9 10 @Override 11 public void run() { 12 try { 13 serverSocketChannel = AsynchronousServerSocketChannel.open(AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10)); 14 serverSocketChannel.bind(new InetSocketAddress(7397)); 15 System.out.println("itstack-demo-netty server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 16 // 等待 17 CountDownLatch latch = new CountDownLatch(1); 18 serverSocketChannel.accept(this, new AioServerChannelInitializer()); 19 latch.await(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 25 public AsynchronousServerSocketChannel serverSocketChannel() { 26 return serverSocketChannel; 27 } 28 29 public static void main(String[] args) { 30 new AioServer().start(); 31 } 32 33}
aio/server/AioServerChannelInitializer.java | 初始化
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class AioServerChannelInitializer extends ChannelInitializer { 7 8 @Override 9 protected void initChannel(AsynchronousSocketChannel channel) throws Exception { 10 channel.read(ByteBuffer.allocate(1024), 10, TimeUnit.SECONDS, null, new AioServerHandler(channel, Charset.forName("GBK"))); 11 } 12 13}
aio/server/AioServerHandler.java | 处理消息
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class AioServerHandler extends ChannelAdapter { 7 8 public AioServerHandler(AsynchronousSocketChannel channel, Charset charset) { 9 super(channel, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 try { 15 System.out.println("微信公众号:bugstack虫洞栈 | 链接报告信息:" + ctx.channel().getRemoteAddress()); 16 //通知客户端链接建立成功 17 ctx.writeAndFlush("微信公众号:bugstack虫洞栈 | 通知服务端链接建立成功" + " " + new Date() + " " + ctx.channel().getRemoteAddress() + "\r\n"); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } 21 } 22 23 @Override 24 public void channelInactive(ChannelHandler ctx) { 25 } 26 27 @Override 28 public void channelRead(ChannelHandler ctx, Object msg) { 29 System.out.println("微信公众号:bugstack虫洞栈 | 服务端收到:" + new Date() + " " + msg + "\r\n"); 30 ctx.writeAndFlush("服务端信息处理Success!\r\n"); 31 } 32 33}
aio/ChannelAdapter.java | Channle适配器模仿Netty
1/** 2 * 消息处理器 3 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 4 * 论坛:http://bugstack.cn 5 * Create by 付政委 on @2019 6 */ 7public abstract class ChannelAdapter implements CompletionHandler<Integer, Object> { 8 9 private AsynchronousSocketChannel channel; 10 private Charset charset; 11 12 public ChannelAdapter(AsynchronousSocketChannel channel, Charset charset) { 13 this.channel = channel; 14 this.charset = charset; 15 if (channel.isOpen()) { 16 channelActive(new ChannelHandler(channel, charset)); 17 } 18 } 19 20 @Override 21 public void completed(Integer result, Object attachment) { 22 try { 23 final ByteBuffer buffer = ByteBuffer.allocate(1024); 24 final long timeout = 60 * 60L; 25 channel.read(buffer, timeout, TimeUnit.SECONDS, null, new CompletionHandler<Integer, Object>() { 26 @Override 27 public void completed(Integer result, Object attachment) { 28 if (result == -1) { 29 try { 30 channelInactive(new ChannelHandler(channel, charset)); 31 channel.close(); 32 } catch (IOException e) { 33 e.printStackTrace(); 34 } 35 return; 36 } 37 buffer.flip(); 38 channelRead(new ChannelHandler(channel, charset), charset.decode(buffer)); 39 buffer.clear(); 40 channel.read(buffer, timeout, TimeUnit.SECONDS, null, this); 41 } 42 43 @Override 44 public void failed(Throwable exc, Object attachment) { 45 exc.printStackTrace(); 46 } 47 }); 48 } catch (Exception e) { 49 e.printStackTrace(); 50 } 51 } 52 53 54 @Override 55 public void failed(Throwable exc, Object attachment) { 56 exc.getStackTrace(); 57 } 58 59 public abstract void channelActive(ChannelHandler ctx); 60 61 public abstract void channelInactive(ChannelHandler ctx); 62 63 // 读取消息抽象类 64 public abstract void channelRead(ChannelHandler ctx, Object msg); 65 66}
AIO案例演示 | 服务端测试
启动AioServer
1itstack-demo-netty aio server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码} 2微信公众号:bugstack虫洞栈 | 链接报告信息:/192.168.1.116:57208 3微信公众号:bugstack虫洞栈 | 服务端收到:Sun Oct 06 18:19:50 CST 2019 hi aio server! helloworld 4 5微信公众号:bugstack虫洞栈 | 服务端收到:Sun Oct 06 18:19:51 CST 2019 hi aio server! helloworld 6 7微信公众号:bugstack虫洞栈 | 服务端收到:Sun Oct 06 18:19:51 CST 2019 hi aio server! helloworld 8 9微信公众号:bugstack虫洞栈 | 服务端收到:Sun Oct 06 18:19:52 CST 2019 hi aio server! helloworld 10 11 12Process finished with exit code -1
BIO案例代码
bio/client/BioClient.java | 客户端
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class BioClient { 7 8 public static void main(String[] args) { 9 try { 10 Socket socket = new Socket("192.168.1.116", 7397); 11 System.out.println("itstack-demo-netty client start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 12 BioClientHandler bioClientHandler = new BioClientHandler(socket, Charset.forName("utf-8")); 13 bioClientHandler.start(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 19}
bio/client/BioClientHandler.java | 消息处理器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class BioClientHandler extends ChannelAdapter { 7 8 public BioClientHandler(Socket socket, Charset charset) { 9 super(socket, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 System.out.println("链接报告LocalAddress:" + ctx.socket().getLocalAddress()); 15 ctx.writeAndFlush("hi! 我是bugstack虫洞栈 BioClient to msg for you \r\n"); 16 } 17 18 @Override 19 public void channelRead(ChannelHandler ctx, Object msg) { 20 System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg); 21 ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n"); 22 } 23 24}
bio/server/BioServer.java | 服务端
1/** 2 * 博客:http://itstack.org 3 * 论坛:http://bugstack.cn 4 * 公众号:bugstack虫洞栈 {获取学习源码} 5 * Create by fuzhengwei on 2019/9/30 6 */ 7public class BioServer extends Thread { 8 9 private ServerSocket serverSocket = null; 10 11 public static void main(String[] args) { 12 BioServer bioServer = new BioServer(); 13 bioServer.start(); 14 } 15 16 @Override 17 public void run() { 18 try { 19 serverSocket = new ServerSocket(); 20 serverSocket.bind(new InetSocketAddress(7397)); 21 System.out.println("itstack-demo-netty server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 22 while (true) { 23 Socket socket = serverSocket.accept(); 24 BioServerHandler handler = new BioServerHandler(socket, Charset.forName("utf-8")); 25 handler.start(); 26 } 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31}
bio/server/BioServerHandler.java | 消息处理器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class BioServerHandler extends ChannelAdapter { 7 8 public BioServerHandler(Socket socket, Charset charset) { 9 super(socket, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 System.out.println("链接报告LocalAddress:" + ctx.socket().getLocalAddress()); 15 ctx.writeAndFlush("hi! 我是bugstack虫洞栈 BioServer to msg for you \r\n"); 16 } 17 18 @Override 19 public void channelRead(ChannelHandler ctx, Object msg) { 20 System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg); 21 ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n"); 22 } 23 24}
bio/ChannelAdapter.java | 适配器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public abstract class ChannelAdapter extends Thread { 7 8 private Socket socket; 9 private ChannelHandler channelHandler; 10 private Charset charset; 11 12 public ChannelAdapter(Socket socket, Charset charset) { 13 this.socket = socket; 14 while (!socket.isConnected()) { 15 break; 16 } 17 channelHandler = new ChannelHandler(this.socket, charset); 18 channelActive(channelHandler); 19 } 20 21 @Override 22 public void run() { 23 try { 24 BufferedReader input = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 25 String str = null; 26 while ((str = input.readLine()) != null) { 27 channelRead(channelHandler, str); 28 } 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 // 链接通知抽象类 35 public abstract void channelActive(ChannelHandler ctx); 36 37 // 读取消息抽象类 38 public abstract void channelRead(ChannelHandler ctx, Object msg); 39 40}
BIO案例测试
启动BioServer
1itstack-demo-netty bio server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码} 2链接报告LocalAddress:/192.168.1.116 32019-10-06 18:28:17 接收到消息:hi bio server! helloworld {结尾是换行符} 42019-10-06 18:28:17 接收到消息:hi bio server! helloworld {结尾是换行符} 52019-10-06 18:28:18 接收到消息:hi bio server! helloworld {结尾是换行符} 62019-10-06 18:28:18 接收到消息:hi bio server! helloworld {结尾是换行符} 72019-10-06 18:28:19 接收到消息:hi bio server! helloworld {结尾是换行符} 82019-10-06 18:28:19 接收到消息:hi bio server! helloworld {结尾是换行符} 9 10Process finished with exit code -1
NIO案例代码
nio/client/NioClient.java | 客户端
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class NioClient { 7 8 public static void main(String[] args) throws IOException { 9 Selector selector = Selector.open(); 10 SocketChannel socketChannel = SocketChannel.open(); 11 socketChannel.configureBlocking(false); 12 13 boolean isConnect = socketChannel.connect(new InetSocketAddress("192.168.1.116", 7397)); 14 if (isConnect) { 15 socketChannel.register(selector, SelectionKey.OP_READ); 16 } else { 17 socketChannel.register(selector, SelectionKey.OP_CONNECT); 18 } 19 System.out.println("itstack-demo-netty client start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 20 new NioClientHandler(selector, Charset.forName("GBK")).start(); 21 } 22 23}
nio/client/NioClientHandler.java | 消息处理器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class NioClientHandler extends ChannelAdapter { 7 8 public NioClientHandler(Selector selector, Charset charset) { 9 super(selector, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 try { 15 System.out.println("链接报告LocalAddress:" + ctx.channel().getLocalAddress()); 16 ctx.writeAndFlush("hi! 我是bugstack虫洞栈 BioClient to msg for you \r\n"); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 } 21 22 @Override 23 public void channelRead(ChannelHandler ctx, Object msg) { 24 System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg); 25 ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n"); 26 } 27 28}
nio/server/NioServer.java | 服务端
1** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class NioServer { 7 8 private Selector selector; 9 private ServerSocketChannel socketChannel; 10 11 public static void main(String[] args) throws IOException { 12 new NioServer().bind(7397); 13 } 14 15 public void bind(int port) { 16 try { 17 selector = Selector.open(); 18 socketChannel = ServerSocketChannel.open(); 19 socketChannel.configureBlocking(false); 20 socketChannel.socket().bind(new InetSocketAddress(port), 1024); 21 socketChannel.register(selector, SelectionKey.OP_ACCEPT); 22 System.out.println("itstack-demo-netty server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}"); 23 new NioServerHandler(selector, Charset.forName("utf-8")).start(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 29}
nio/server/NioServerHandler.java | 消息处理器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public class NioServerHandler extends ChannelAdapter { 7 8 public NioServerHandler(Selector selector, Charset charset) { 9 super(selector, charset); 10 } 11 12 @Override 13 public void channelActive(ChannelHandler ctx) { 14 try { 15 System.out.println("链接报告LocalAddress:" + ctx.channel().getLocalAddress()); 16 ctx.writeAndFlush("hi! 我是bugstack虫洞栈 BioServer to msg for you \r\n"); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 } 21 22 @Override 23 public void channelRead(ChannelHandler ctx, Object msg) { 24 System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg); 25 ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n"); 26 } 27 28}
nio/ChannelAdapter.java | 适配器
1/** 2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。 3 * 论坛:http://bugstack.cn 4 * Create by 付政委 on @2019 5 */ 6public abstract class ChannelAdapter extends Thread { 7 8 private Selector selector; 9 10 private ChannelHandler channelHandler; 11 private Charset charset; 12 13 public ChannelAdapter(Selector selector, Charset charset) { 14 this.selector = selector; 15 this.charset = charset; 16 } 17 18 @Override 19 public void run() { 20 while (true) { 21 try { 22 selector.select(1000); //Selects a set of keys whose corresponding channels are ready for I/O 23 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 24 Iterator<SelectionKey> it = selectedKeys.iterator(); 25 SelectionKey key = null; 26 while (it.hasNext()) { 27 key = it.next(); 28 it.remove(); 29 handleInput(key); 30 } 31 } catch (Exception ignore) { 32 } 33 } 34 } 35 36 private void handleInput(SelectionKey key) throws IOException { 37 if (!key.isValid()) return; 38 39 // 客户端SocketChannel 40 Class<?> superclass = key.channel().getClass().getSuperclass(); 41 if (superclass == SocketChannel.class){ 42 SocketChannel socketChannel = (SocketChannel) key.channel(); 43 if (key.isConnectable()) { 44 if (socketChannel.finishConnect()) { 45 channelHandler = new ChannelHandler(socketChannel, charset); 46 channelActive(channelHandler); 47 socketChannel.register(selector, SelectionKey.OP_READ); 48 } else { 49 System.exit(1); 50 } 51 } 52 } 53 54 // 服务端ServerSocketChannel 55 if (superclass == ServerSocketChannel.class){ 56 if (key.isAcceptable()) { 57 ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); 58 SocketChannel socketChannel = serverSocketChannel.accept(); 59 socketChannel.configureBlocking(false); 60 socketChannel.register(selector, SelectionKey.OP_READ); 61 62 channelHandler = new ChannelHandler(socketChannel, charset); 63 channelActive(channelHandler); 64 } 65 } 66 67 if (key.isReadable()) { 68 SocketChannel socketChannel = (SocketChannel) key.channel(); 69 ByteBuffer readBuffer = ByteBuffer.allocate(1024); 70 int readBytes = socketChannel.read(readBuffer); 71 if (readBytes > 0) { 72 readBuffer.flip(); 73 byte[] bytes = new byte[readBuffer.remaining()]; 74 readBuffer.get(bytes); 75 channelRead(channelHandler, new String(bytes, charset)); 76 } else if (readBytes < 0) { 77 key.cancel(); 78 socketChannel.close(); 79 } 80 } 81 } 82 83 // 链接通知抽象类 84 public abstract void channelActive(ChannelHandler ctx); 85 86 // 读取消息抽象类 87 public abstract void channelRead(ChannelHandler ctx, Object msg); 88 89}
NIO案例测试
启动NioServer
1itstack-demo-netty nio server start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码} 2链接报告LocalAddress:/192.168.1.116:7397 32019-10-06 18:33:32 接收到消息:hi bio server! helloworld {结尾无换行符} 42019-10-06 18:33:32 接收到消息:hi bio server! helloworld {结尾无换行符} 52019-10-06 18:33:32 接收到消息:hi bio server! helloworld {结尾无换行符} 62019-10-06 18:33:33 接收到消息:hi bio server! helloworld {结尾无换行符} 72019-10-06 18:33:33 接收到消息:hi bio server! helloworld {结尾无换行符} 8 9Process finished with exit code -1