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);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章