AIO实现Echo

首先定义服务端

先定义服务端的关闭,这个在多处函数中用得着:只要是实现了closeable接口的都可以调用

private void close(Closeable closeable) throws IOException {
        if(closeable != null){
            closeable.close();
        }
}

然后是我们用到的主要的函数:

public void start() throws IOException {
        try {
            serverSocketChannel = AsynchronousServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(hosts,port));
            System.out.println("start server");

            while (true) {
                serverSocketChannel.accept(null,new AcceptHandler()); // 1
                System.in.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            close(serverSocketChannel);
        }
    }

这里我们只解释while循环里面:这里等待客户端的连接,第一个参数是个attachment,也就是附件,需要传入到后面的AcceptHandler()处理的参数,这里为空。这里的异步调用,返回的结果交给Accepthandler处理,为了防止频繁调用,影响性能,这里用read,进行手动阻塞。

接下来是AcceptHandler()的定义

private class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel,Object>{


        @Override
        public void completed(AsynchronousSocketChannel result, Object attachment) {
            if(serverSocketChannel.isOpen()){
                serverSocketChannel.accept(null,this); // 0
            }
            AsynchronousSocketChannel clientChannel = result;  // 1
            if(clientChannel != null && clientChannel.isOpen()){
                ClientHandler handler = new ClientHandler(clientChannel); // 2
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                Map<String, Object> info = new HashMap<>();
                info.put("type","read");
                info.put("buffer",buffer);
                clientChannel.read(buffer,info,handler); // 3
            }
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("error");
        }
    }

这里需要实现CompletionHandler接口,接口有两个方法,我们只实现调用成功的方法。
这里的result是前面accept调用成功返回的结果,后面的attachment是我们传入的附件,我们上一步传入的附件为空。
【0】我们继续让accept继续监听,附件依旧为空,处理类还是设置为这个,这里用this指代。
【2】我们定义一个类用于客户端异步的响应处理.
【3】客户端把内容读到buffer里面,把Map作为attachment,用于handler响应处理


下面是相应的handler处理类:

public class ClientHandler implements CompletionHandler<Integer, Object> {

    private AsynchronousSocketChannel clientChannel;

    public ClientHandler(AsynchronousSocketChannel clientChannel) {
        this.clientChannel = clientChannel;
    }

    @Override
    public void completed(Integer result, Object attachment) {  // 0
         Map<String,Object> info = (Map<String, Object>) attachment;
         String type = (String) info.get("type");
         if("read".equals(type)){
             ByteBuffer buffer = (ByteBuffer) info.get("buffer");
             buffer.flip();
             info.put("type","write");
             clientChannel.write(buffer,info,this);
             buffer.clear();
         }else if("write".equals(type)){
             ByteBuffer buffer = ByteBuffer.allocate(1024);
             info = new HashMap<>();
             info.put("type","read");
             info.put("buffer",buffer);
             clientChannel.read(buffer,info,this);
         }
    }

    @Override
    public void failed(Throwable exc, Object attachment) {
    }
}

这里和上面的差不多,read函数返回的是一个Integer,attachment传入的是一个map,我们可以根据map得到请求处理的类型,不同的类型,我们分别进行相应的处理。


下面是客户端

public void start() throws IOException {
        try {
            SocketChannel = AsynchronousSocketChannel.open();
            Future<Void> future = SocketChannel.connect(new InetSocketAddress(hosts,port));
            future.get();

            BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
            while(true){
                String input = consoleReader.readLine();
                byte [] inputbyte = input.getBytes();
                ByteBuffer buffer = ByteBuffer.wrap(inputbyte);
                Future<Integer> writeResult = SocketChannel.write(buffer);

                writeResult.get();
                buffer.flip();
                Future<Integer> readResult = SocketChannel.read(buffer);
                readResult.get();

                String echo = new String(buffer.array());
                buffer.clear();
                System.out.println(echo);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            close(SocketChannel);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值