AsynchronousServerSocketChannel
assc.accept(this, new ServerCompletionHandler()); 第一个参数是服务器的处理类,第二个参数当服务接受到客户端的连接之后,用来处理客户端的连接
这里accept并不是一直阻塞的,会继续向下面执行,为了保证服务器端程序一直运行存在,所以这里使用了
//进行阻塞。第一个参数可以是null
assc.accept(this, new ServerCompletionHandler());
//一直阻塞 不让服务器停止
Thread.sleep(Integer.MAX_VALUE);
this就是当前的服务器端的实例对象,ServerCompletionHandler用来处理客户端请求数据的,必须实现implements CompletionHandler<AsynchronousSocketChannel, Server>
第一个参数AsynchronousSocketChannel就是当前服务器端的Channel通道对象,第二参数和assc.accept(this, new ServerCompletionHandler());中的第一个参数必须一一对应
实现CompletionHandler接口必须实现下面的两个方法
completed
failed
@Override
public void completed(AsynchronousSocketChannel asc, Server attachment) {
//当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞
attachment.assc.accept(attachment, this);
read(asc);
}
attachment就是传递进来的服务器对象,attachment.assc就是Server类的channel对象,然后在调用channel对象对象的accept对象,就和在server端调用assc.accept(this, new ServerCompletionHandler());一样
在 completed函数中进行递归调用assc.accept(this, new ServerCompletionHandler())
接下来就可以读取客户端连接的数据了read(asc);
来一个客户端就调用一次assc.accept(this, new ServerCompletionHandler()),所以在在 completed函数中进行递归调用assc.accept(this, new ServerCompletionHandler())进行递归调用
我们来看下客户端服务器的代码:
package bhz.aio; import java.net.InetSocketAddress; import java.nio.channels.AsynchronousChannelGroup; import java.nio.channels.AsynchronousServerSocketChannel; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Server { //线程池 private ExecutorService executorService; //线程组 private AsynchronousChannelGroup threadGroup; //服务器通道 public AsynchronousServerSocketChannel assc; public Server(int port){ try { //创建一个缓存池 executorService = Executors.newCachedThreadPool(); //创建线程组,1表示初始化一个线程池 threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1); //创建服务器通道 assc = AsynchronousServerSocketChannel.open(threadGroup); //进行绑定,这里就没有nio的seletor操作 assc.bind(new InetSocketAddress(port)); System.out.println("server start , port : " + port); //进行阻塞。第一个参数可以是null assc.accept(this, new ServerCompletionHandler()); //一直阻塞 不让服务器停止 Thread.sleep(Integer.MAX_VALUE); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Server server = new Server(8765); } }
package bhz.aio; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutionException; public class ServerCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> { @Override public void completed(AsynchronousSocketChannel asc, Server attachment) { //当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞 attachment.assc.accept(attachment, this); read(asc); } //AsynchronousSocketChannel客户端的通道 private void read(final AsynchronousSocketChannel asc) { //读取数据,异步的读取数据 ByteBuffer buf = ByteBuffer.allocate(1024); asc.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer resultSize, ByteBuffer attachment) { //进行读取之后,重置标识位 attachment.flip(); //获得读取的字节数 System.out.println("Server -> " + "收到客户端的数据长度为:" + resultSize); //获取读取的数据 String resultData = new String(attachment.array()).trim(); System.out.println("Server -> " + "收到客户端的数据信息为:" + resultData); String response = "服务器响应, 收到了客户端发来的数据: " + resultData; write(asc, response); } @Override public void failed(Throwable exc, ByteBuffer attachment) { exc.printStackTrace(); } }); } private void write(AsynchronousSocketChannel asc, String response) { try { ByteBuffer buf = ByteBuffer.allocate(1024); buf.put(response.getBytes()); buf.flip(); asc.write(buf).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } @Override public void failed(Throwable exc, Server attachment) { exc.printStackTrace(); } }
package bhz.aio; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.util.concurrent.ExecutionException; public class Client implements Runnable{ private AsynchronousSocketChannel asc ; public Client() throws Exception { asc = AsynchronousSocketChannel.open(); } public void connect(){ asc.connect(new InetSocketAddress("127.0.0.1", 8765)); } public void write(String request){ try { asc.write(ByteBuffer.wrap(request.getBytes())).get(); read(); } catch (Exception e) { e.printStackTrace(); } } private void read() { ByteBuffer buf = ByteBuffer.allocate(1024); try { asc.read(buf).get(); buf.flip(); byte[] respByte = new byte[buf.remaining()]; buf.get(respByte); System.out.println(new String(respByte,"utf-8").trim()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } @Override public void run() { while(true){ } } public static void main(String[] args) throws Exception { Client c1 = new Client(); c1.connect(); Client c2 = new Client(); c2.connect(); Client c3 = new Client(); c3.connect(); new Thread(c1, "c1").start(); new Thread(c2, "c2").start(); new Thread(c3, "c3").start(); Thread.sleep(1000); c1.write("c1 aaa"); c2.write("c2 bbbb"); c3.write("c3 ccccc"); } }
程序运行的结果是:
服务器响应, 收到了客户端发来的数据: c1 aaa
服务器响应, 收到了客户端发来的数据: c2 bbbb
服务器响应, 收到了客户端发来的数据: c3 ccccc