分享

netty案例,netty4.1基础入门篇零《初入JavaIO之门BIO、NIO、AIO实战练习》

 小傅哥 2021-12-13

作者:付政委

祝努力的你,所求皆如愿 所行化坦途

微信公众号:bugstack虫洞栈 | 1k+关注
跟着案例学Netty,Netty4.x案例从简单入门到应用实战,全篇35章节优秀案例+源码分析[基础篇(13)、中级篇(12)、高级篇(3章+)、源码分析篇(6)],以上章节全部完成并不断持续更新中,欢迎关注学习&下载专题源码

前言介绍

在Java中,提供了一些关于使用IO的API,可以供开发者来读写外部数据和文件,我们称这些API为Java IO。IO是Java中比较重要知识点,且比较难学习的知识点。并且随着Java的发展为提供更好的数据传输性能,目前有三种IO共存;分别是BIO、NIO和AIO。

微信公众号:bugstack虫洞栈 | 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://
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), nullnew 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://
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://
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(thisnew 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://
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, nullnew AioServerHandler(channel, Charset.forName("GBK")));
11    }
12
13}

aio/server/AioServerHandler.java | 处理消息

1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。
3 * 论坛:http://
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://
5 * Create by 付政委 on @2019
6 */

7public abstract class ChannelAdapter implements CompletionHandler<IntegerObject{
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, nullnew 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, nullthis);
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
微信公众号:bugstack虫洞栈 | AIO案例测试

BIO案例代码

bio/client/BioClient.java | 客户端

1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。
3 * 论坛:http://
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://
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://
3 * 论坛:http://
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://
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://
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
微信公众号:bugstack虫洞栈 | BIO案例测试

NIO案例代码

nio/client/NioClient.java | 客户端

1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例,以最易学习编程的方式分享知识,让萌新、小白、大牛都能有所收获。目前已完成的专题有;Netty4.x从入门到实战、用Java实现JVM、基于JavaAgent的全链路监控等,其他更多专题还在排兵布阵中。
3 * 论坛:http://
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://
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://
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://
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://
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

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多