netty权威指南学习笔记一——NIO入门(4)AIO

  NIO2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。异步通道提供以下两种方式获取操作结果。

  1、通过java.util.concurrent.Future 类来表示异步操作的结果;

  2、在执行异步操作的时候传入一个java.io.channels。

  ComplementHandler接口的实现类作为操作完成的回调。

  NIO2.0的异步套接字通道是真正的异步非阻塞I/O,它不需要通过多路复用器(Selector)对注册的通道进行轮询操作即可实现异步读写,从而简化了NIO编程模型。

  改造后的代码

server端代码:

  

 1 package com.example.biodemo;
 2 
 3 
 4 import java.io.*;
 5 import java.net.ServerSocket;
 6 import java.net.Socket;
 7 
 8 public class TimeServer {
 9     public static void main(String[] args) throws IOException {
10         int port = 8092;
11         if (args != null && args.length > 0) {
12             try {
13                 port = Integer.valueOf(args[0]);
14             } catch (NumberFormatException e) {
15                 port = 8092;
16             }
17         }
18         AsyncTimeServerHandler timeServer = new AsyncTimeServerHandler(port);
19         new Thread(timeServer,"AsychronousTimeServerHandler").start();
20 
21 
22 
23         // ===================改造代码为AIO将以下内容注释掉=================================
24 
25 //        创建多路复用线程类并初始化多路复用器,绑定端口等以及轮询注册功能
26  /*       MultiplexerTimeServer timeServer = new MultiplexerTimeServer(port);
27 //        启动多路复用类线程负责轮询多路复用器Selector,IO数据处理等操作
28         new Thread(timeServer, "NIO-MultiplexerTimeSever-001").start();*/
29 
30 // ===================以下内容注释掉=================================
31 
32        /* ServerSocket server = null;
33         try {
34             server = new ServerSocket(port);
35             System.out.println("the timeServer is start in port :" + port);
36             Socket socket = null;
37 //           引入线程池start
38             TimeServerHandlerExecutePool singleExecutor = new TimeServerHandlerExecutePool(50,10000);
39             while (true) {
40                 socket = server.accept();
41 //           替换BIO中new Thread(new TimeServerHandler(socket)).start();为下一行代码
42                 singleExecutor.execute(new TimeServerHandler(socket));
43 //           引入线程池end
44 
45             }
46         } finally {
47             if (server != null) {
48                 System.out.println("the time server close");
49                 server.close();
50                 server = null;
51             }
52         }*/
53 
54     }
55 }

异步时间服务处理器

 1 package com.example.biodemo;
 2 
 3 import java.io.IOException;
 4 import java.net.InetSocketAddress;
 5 import java.nio.channels.AsynchronousServerSocketChannel;
 6 import java.util.concurrent.CountDownLatch;
 7 
 8 public class AsyncTimeServerHandler implements Runnable{
 9      private int port;
10 //     添加它作用是在完成一组正在执行的操作之前,允许当前线程一直阻塞
11      CountDownLatch latch;
12      AsynchronousServerSocketChannel asynchronousServerSocketChannel;
13     public AsyncTimeServerHandler(int port) {
14         this.port=port;
15         try {
16 //            创建异步服务套接字通道
17             asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
18 //            绑定监听端口
19             asynchronousServerSocketChannel.bind(new InetSocketAddress(port));
20             System.out.println("The time server is start in port"+port);
21         } catch (IOException e) {
22             e.printStackTrace();
23         }
24     }
25 
26     @Override
27     public void run() {
28     latch =new CountDownLatch(1);
29 //    接收客户端的连接
30     doAccept();
31         try {
32             latch.await();
33         } catch (InterruptedException e) {
34             e.printStackTrace();
35         }
36 
37     }
38 
39     private void doAccept() {
40 //        AcceptCompletionHandler用于接收accept操作成功的通知消息
41 //        accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler):接受连接,并为连接绑定一个CompletionHandler处理Socket连接
42         asynchronousServerSocketChannel.accept(this,new AcceptCompletionHandler());
43     }
44 }

AcceptCompletionHandle

 1 package com.example.biodemo;
 2 
 3 import java.nio.ByteBuffer;
 4 import java.nio.channels.AsynchronousServerSocketChannel;
 5 import java.nio.channels.AsynchronousSocketChannel;
 6 import java.nio.channels.CompletionHandler;
 7 
 8 public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel,AsyncTimeServerHandler>{
 9 
10     @Override
11     public void completed(AsynchronousSocketChannel result, AsyncTimeServerHandler attachment) {
12         //再次让asynchronousServerSocketChannel对象调用accept方法是
13         //调用AsynchronousServerSocketChannel的accept方法后,如果有新的客户端接入,
14         // 系统将回调我们传入的CompletionHandler实例的completed方法,表示新客户端连接成功。
15         // 因为AsynchronousServerSocketChannel可以接受成千上万个客户端,所以需要继续调用它的accept方法,
16         // 接受其他客户端连接,最终形成一个环;每当一个客户端连接成功后,再异步接受新的客户端连接
17         attachment.asynchronousServerSocketChannel.accept(attachment,this);
18 //        据上,链路建立成功,服务端需要接受客户端新请求消息,
19         ByteBuffer buffer = ByteBuffer.allocate(1024);
20 //        调用read方法进行异步读操作
21         result.read(buffer,buffer,new ReadCompletionHandler(result));
22     }
23 
24     @Override
25     public void failed(Throwable exc, AsyncTimeServerHandler attachment) {
26         exc.printStackTrace();
27         attachment.latch.countDown();
28     }
29 
30 
31 }

ReadCompletionHandler

 1 package com.example.biodemo;
 2 
 3 import java.io.IOException;
 4 import java.io.UnsupportedEncodingException;
 5 import java.nio.ByteBuffer;
 6 import java.nio.channels.AsynchronousSocketChannel;
 7 import java.nio.channels.CompletionHandler;
 8 import java.util.Date;
 9 
10 public class ReadCompletionHandler implements CompletionHandler<Integer,ByteBuffer> {
11 
12     private AsynchronousSocketChannel channel;
13 
14     public ReadCompletionHandler(AsynchronousSocketChannel channel) {
15         if(this.channel==null){
16             this.channel=channel;
17         }
18     }
19 
20     @Override
21     public void completed(Integer result, ByteBuffer attachment) {
22         attachment.flip();
23         byte[] body = new byte[attachment.remaining()];
24         attachment.get(body);
25         try {
26             String req = new String(body,"utf-8");
27             System.out.println("The time server recerve order : "+req);
28             String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(req)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
29             doWriter(currentTime);
30         } catch (UnsupportedEncodingException e) {
31             e.printStackTrace();
32         }
33     }
34 
35     private void doWriter(String currentTime) {
36         if (currentTime != null && currentTime.trim().length() > 0) {
37             byte[] bytes = currentTime.getBytes();
38             ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
39             writeBuffer.put(bytes);
40             writeBuffer.flip();
41             channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
42                 @Override
43                 public void completed(Integer result, ByteBuffer attachment) {
44                     //如果没有发送完继续发送
45                     if (attachment.hasRemaining()) {
46                         channel.write(attachment, attachment, this);
47                     }
48                 }
49                 @Override
50                 public void failed(Throwable exc, ByteBuffer attachment) {
51                     try {
52                         channel.close();
53                     } catch (IOException e) {
54                     }
55                 }
56             });
57             }
58     }
59     @Override
60     public void failed(Throwable exc, ByteBuffer attachment) {
61         try {
62             this.channel.close();
63         } catch (IOException e) {
64             e.printStackTrace();
65         }
66     }
67 }

客户端的代码

 1 package com.example.biodemo;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 
 6 public class TimeClient {
 7     public static void main(String[] args) {
 8         int port = 8092;
 9         if (args != null && args.length > 0) {
10             try {
11                 port = Integer.valueOf(args[0]);
12             } catch (NumberFormatException ne) {
13                 port = 8092;
14             }
15         }
16         new Thread(new AsyncTimeClientHandler("127.0.0.1",port)).start();
17 
18 
19 
20 //        new Thread(new TimeClientHandles("127.0.0.1",port),"TimeClient-001").start();
21       /* 代码改造注释掉以下代码
22        Socket socket = null;
23         BufferedReader in = null;
24         PrintWriter out = null;
25         try {
26             socket = new Socket("127.0.0.1", port);
27             System.out.println(socket.getInputStream());
28             in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
29             out = new PrintWriter(socket.getOutputStream(), true);
30             out.println("QUERY TIME ORDER");
31             System.out.println("send order 2 server succeed.");
32             String resp = in.readLine();
33             System.out.println("now is :" + resp);
34         } catch (IOException e1) {
35 
36         } finally {
37             if (out != null) {
38                 out.close();
39                 out = null;
40             }
41 
42             if (in != null) {
43                 try {
44                     in.close();
45                 } catch (IOException e2) {
46                     e2.printStackTrace();
47                 }
48                 in = null;
49                 if (socket != null) {
50                     try {
51                         socket.close();
52                     } catch (IOException e3) {
53                         e3.printStackTrace();
54                     }
55 
56                 }
57                 socket = null;
58             }
59         }*/
60     }
61 }

AsyncTimeClientHandler

  1 package com.example.biodemo;
  2 
  3 import java.io.IOException;
  4 import java.io.UnsupportedEncodingException;
  5 import java.net.InetSocketAddress;
  6 import java.nio.ByteBuffer;
  7 import java.nio.channels.AsynchronousSocketChannel;
  8 import java.nio.channels.CompletionHandler;
  9 import java.util.concurrent.CountDownLatch;
 10 
 11 public class AsyncTimeClientHandler implements CompletionHandler<Void, AsyncTimeClientHandler>, Runnable {
 12     private AsynchronousSocketChannel asynchronousSocketChannel;
 13     private String host;
 14     private int port;
 15     private CountDownLatch latch;
 16 
 17     public AsyncTimeClientHandler(String host, int port) {
 18         this.host = host == null ? "127.0.0.1" : host;
 19         this.port = port;
 20         try {
 21             asynchronousSocketChannel = AsynchronousSocketChannel.open();
 22         } catch (IOException e) {
 23             e.printStackTrace();
 24         }
 25     }
 26 
 27     @Override
 28     public void run() {
 29         latch = new CountDownLatch(1);
 30         asynchronousSocketChannel.connect(new InetSocketAddress(host, port), this, this);
 31         try {
 32             latch.await();
 33         } catch (InterruptedException e) {
 34             e.printStackTrace();
 35         }
 36         try {
 37             asynchronousSocketChannel.close();
 38         } catch (IOException e) {
 39             e.printStackTrace();
 40         }
 41     }
 42 
 43 
 44     @Override
 45     public void completed(Void result, AsyncTimeClientHandler attachment) {
 46         byte[] req = "QUERY TIME ORDER".getBytes();
 47         ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
 48         writeBuffer.put(req);
 49         writeBuffer.flip();
 50         asynchronousSocketChannel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
 51             @Override
 52             public void completed(Integer result, ByteBuffer attachment) {
 53                 if (attachment.hasRemaining()) {
 54                     asynchronousSocketChannel.write(attachment, attachment, this);
 55                 } else {
 56                     ByteBuffer readBuffer = ByteBuffer.allocate(1024);
 57                     asynchronousSocketChannel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {
 58                         @Override
 59                         public void completed(Integer result, ByteBuffer attachment) {
 60                             attachment.flip();
 61                             byte[] bytes = new byte[attachment.remaining()];
 62                             attachment.get(bytes);
 63                             String body = null;
 64                             try {
 65                                 body = new String(bytes, "utf-8");
 66                                 System.out.println(body);
 67                                 System.out.println("Now is :" + body);
 68                                 latch.countDown();
 69                             } catch (UnsupportedEncodingException e) {
 70                                 e.printStackTrace();
 71                             }
 72 
 73                         }
 74 
 75                         @Override
 76                         public void failed(Throwable exc, ByteBuffer attachment) {
 77                             try {
 78                                 asynchronousSocketChannel.close();
 79                                 latch.countDown();
 80                             } catch (IOException e) {
 81                                 e.printStackTrace();
 82                             }
 83                         }
 84                     });
 85                 }
 86             }
 87 
 88             @Override
 89             public void failed(Throwable exc, ByteBuffer attachment) {
 90                 try {
 91                     asynchronousSocketChannel.close();
 92                     latch.countDown();
 93                 } catch (IOException e) {
 94                     e.printStackTrace();
 95                 }
 96             }
 97         });
 98     }
 99 
100     @Override
101     public void failed(Throwable exc, AsyncTimeClientHandler attachment) {
102         exc.printStackTrace();
103         try {
104             asynchronousSocketChannel.close();
105             latch.countDown();
106         } catch (IOException e) {
107             e.printStackTrace();
108         }
109     }
110 }

  学到这里我们对NIO编程已经有了一个感性认识。

posted @ 2018-07-08 17:15  醉逍遥_001  阅读(294)  评论(0编辑  收藏  举报