Reprinted: http://m.blog.csdn.net/article/details?id=51512200
AIO asynchronous non-blocking IO instance: the client sends a mathematical expression, and the server receives the calculation and returns it to the client.
1. Server
包括,Server、ServerHandler、ServerWriteHandler、ServerReadHandler、AcceptHandler、Calculator
1.1 Start the program:
public class Server { private static int DEFAULT_PORT = 12345; private static AsyncServerHandler serverHandle; public volatile static long clientCount = 0; public static void start(){ start(DEFAULT_PORT); } public static synchronized void start(int port){ if(serverHandle!=null) return; serverHandle = new AsyncServerHandler(port); new Thread(serverHandle,"Server").start(); } public static void main(String[] args){ Server.start(); } }
1.2 AsyncServerHandler
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.AsynchronousServerSocketChannel; import java.util.concurrent.CountDownLatch; public class AsyncServerHandler implements Runnable{ public CountDownLatch latch; public AsynchronousServerSocketChannel channel; public AsyncServerHandler(int port) { try { //create server channel channel = AsynchronousServerSocketChannel.open(); // bind port channel.bind(new InetSocketAddress(port)); System.out.println("Server started, port number: " + port); } catch (IOException e) { e.printStackTrace (); } } @Override public void run() { //CountDownLatch initialization //What it does: Allows the current scene to block until a set of ongoing operations is completed //Here, let the scene block here to prevent the server from exiting after the execution is complete //You can also use while(true)+sleep //The generation environment does not need to worry about this problem, thinking that the server will not exit latch = new CountDownLatch(1); // used to receive connections from clients channel.accept(this,new AcceptHandler()); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace (); } } }
1.3 AcceptHandler
import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; //Receive client connections as handler public class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncServerHandler>{ @Override public void completed(AsynchronousSocketChannel channel, AsyncServerHandler serverHandler) { //Continue to accept requests from other clients Server.clientCount++; System.out.println("Number of connected clients: " + Server.clientCount); serverHandler.channel.accept(serverHandler, this); //Create a new Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); //Asynchronously read the third parameter is the business Handler that receives the message callback channel.read(buffer, buffer, new ServerReadHandler(channel)); } @Override public void failed(Throwable exc, AsyncServerHandler serverHandler) { exc.printStackTrace(); serverHandler.latch.countDown(); } }
1.4 ServerReadHandler
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; public class ServerReadHandler implements CompletionHandler<Integer, ByteBuffer> { // used to read half-packet messages and send responses private AsynchronousSocketChannel channel; public ServerReadHandler(AsynchronousSocketChannel channel) { this.channel = channel; } //Processing after reading the message @Override public void completed(Integer result, ByteBuffer attachment) { //flip operation attachment.flip(); //according to byte[] message = new byte[attachment.remaining()]; attachment.get(message); try { String expression = new String(message, "UTF-8"); System.out.println("Server received message: " + expression); String calrResult = null; try{ calrResult = Calculator.cal(expression).toString(); }catch(Exception e){ calrResult = "Calculation error: " + e.getMessage(); } // send message to client doWrite(calrResult); } catch (UnsupportedEncodingException e) { e.printStackTrace (); } } //send messages private void doWrite(String result) { byte[] bytes = result.getBytes(); ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length); writeBuffer.put(bytes); writeBuffer.flip(); //Asynchronous write data parameters are the same as the previous read channel.write(writeBuffer, writeBuffer,new ServerWriteHandler(channel)); } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { this.channel.close(); } catch (IOException e) { e.printStackTrace (); } } }
1.5 Server WriteHandler
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; public class ServerWriteHandler implements CompletionHandler<Integer, ByteBuffer>{ private AsynchronousSocketChannel channel; public ServerWriteHandler(AsynchronousSocketChannel channel) { this.channel = channel; } @Override public void completed(Integer result, ByteBuffer buffer) { //If not sent, continue to send until completed if (buffer.hasRemaining()) channel.write(buffer, buffer, this); else{ //Create a new Buffer ByteBuffer readBuffer = ByteBuffer.allocate(1024); //Asynchronously read the third parameter is the business Handler that receives the message callback channel.read(readBuffer, readBuffer, new ServerReadHandler(channel)); } } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { channel.close(); } catch (IOException e) { } } }
1.6 Calculator
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class Calculator { private final static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); public static Object cal(String expression) throws ScriptException{ return jse.eval(expression); } }
2. Customer service
包括 Client、ClientHandler、ClientWriteHandler、ClientReadHandler
2.1 Launcher
import java.util.Scanner; public class Client { private static String DEFAULT_HOST = "127.0.0.1"; private static int DEFAULT_PORT = 12345; private static AsyncClientHandler clientHandle; public static void start(){ start(DEFAULT_HOST,DEFAULT_PORT); } public static synchronized void start(String ip,int port){ if(clientHandle!=null) return; clientHandle = new AsyncClientHandler(ip,port); new Thread(clientHandle,"Client").start(); } // send message to server public static boolean sendMsg(String msg) throws Exception{ if(msg.equals("q")) return false; clientHandle.sendMsg(msg); return true; } @SuppressWarnings("resource") public static void main(String[] args) throws Exception{ Client.start(); System.out.println("Please enter the request message: "); Scanner scanner = new Scanner(System.in); while(Client.sendMsg(scanner.nextLine())); } }
2.2 AsyncClientHandler
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.CountDownLatch; public class AsyncClientHandler implements CompletionHandler<Void, AsyncClientHandler>, Runnable{ private AsynchronousSocketChannel clientChannel; private String host; private int port; private CountDownLatch latch; public AsyncClientHandler(String host, int port) { this.host = host; this.port = port; try { //Create an asynchronous client channel clientChannel = AsynchronousSocketChannel.open(); } catch (IOException e) { e.printStackTrace (); } } @Override public void run() { //Create CountDownLatch to wait latch = new CountDownLatch(1); //Initiate an asynchronous connection operation, the callback parameter is the class itself, if the connection is successful, the completed method will be called back clientChannel.connect(new InetSocketAddress(host, port), this, this); try { latch.await(); } catch (InterruptedException e1) { e1.printStackTrace(); } try { clientChannel.close(); } catch (IOException e) { e.printStackTrace (); } } //Successful connection to the server //means the TCP three-way handshake is complete @Override public void completed(Void result, AsyncClientHandler attachment) { System.out.println("The client successfully connected to the server..."); } //Connection failure @Override public void failed(Throwable exc, AsyncClientHandler attachment) { System.err.println("Failed to connect to the server..."); exc.printStackTrace(); try { clientChannel.close(); latch.countDown(); } catch (IOException e) { e.printStackTrace (); } } // send message to server public void sendMsg(String msg){ byte[] req = msg.getBytes(); ByteBuffer writeBuffer = ByteBuffer.allocate(req.length); writeBuffer.put(req); writeBuffer.flip(); // write asynchronously clientChannel.write(writeBuffer, writeBuffer,new ClientWriteHandler(clientChannel, latch)); } }
2.3 ClientWriteHandler
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.CountDownLatch; public class ClientWriteHandler implements CompletionHandler<Integer, ByteBuffer>{ private AsynchronousSocketChannel clientChannel; private CountDownLatch latch; public ClientWriteHandler(AsynchronousSocketChannel clientChannel,CountDownLatch latch) { this.clientChannel = clientChannel; this.latch = latch; } @Override public void completed(Integer result, ByteBuffer buffer) { //Complete the writing of all data if (buffer.hasRemaining()) { clientChannel.write(buffer, buffer, this); } else { //read data ByteBuffer readBuffer = ByteBuffer.allocate(1024); clientChannel.read(readBuffer,readBuffer,new ClientReadHandler(clientChannel, latch)); } } @Override public void failed(Throwable exc, ByteBuffer attachment) { System.err.println("Failed to send data..."); try { clientChannel.close(); latch.countDown(); } catch (IOException e) { } } }
2.4 ClientReadHandler
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.CountDownLatch; public class ClientReadHandler implements CompletionHandler<Integer, ByteBuffer> { private AsynchronousSocketChannel clientChannel; private CountDownLatch latch; public ClientReadHandler(AsynchronousSocketChannel clientChannel,CountDownLatch latch) { this.clientChannel = clientChannel; this.latch = latch; } @Override public void completed(Integer result,ByteBuffer buffer) { buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); String body; try { body = new String(bytes,"UTF-8"); System.out.println("The client received the result: "+ body); } catch (UnsupportedEncodingException e) { e.printStackTrace (); } } @Override public void failed(Throwable exc,ByteBuffer attachment) { System.err.println("Data read failed..."); try { clientChannel.close(); latch.countDown(); } catch (IOException e) { } } }
3. Execution results
Server started, port number: 12345 Please enter a request message: Client successfully connected to server... Number of connected clients: 1 123456+789+456 Server received message: 123456+789+456 Client received result: 124701 9526*56 Server received message: 9526*56 Client received result: 533456