AIO入門案例客戶端的代碼具體實現以及詳細註釋

package com.nio.aio.client;

import java.io.IOException;

public class AIOClient {
    public static void main(String[] args)throws IOException {
        // 設置要監聽的端口
        int port = 8788;
        if (args != null && args.length > 0){
            try {
                port = Integer.valueOf(args[0]);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        // 創建AIOTimeClientHandler線程來處理異步連接和讀寫操作
        new Thread(new AIOTimeClientHandler("localhost", port), "AIO-client-Handler").start();

    }

}
package com.nio.aio.client;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
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 AIOTimeClientHandler implements CompletionHandler<Void, AIOTimeClientHandler>, Runnable {
    private AsynchronousSocketChannel client;
    private String host;
    private int port;
    private CountDownLatch latch;

    // 構造方法
    public AIOTimeClientHandler(String host, int port) {
        this.host = host;
        this.port = port;
        try {
            // 創建AsynchronousSocketChannel對象
            client = AsynchronousSocketChannel.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        // 創建CountDownLatch進行等待,防止異步操作沒有執行完成線程就退出
        latch = new CountDownLatch(1);
        // 發起異步操作
        /**
         * 參數說明
         * 1 該通道要連接到的遠程地址
         * 2 用於回調通知時作爲入參被傳遞
         * 3 異步操作回調通知接口
         */
        client.connect(new InetSocketAddress(host,port), this, this);
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void completed(Void result, AIOTimeClientHandler attachment) {
        // 創建發給服務端的消息
        byte[] req = "AIO TIME TEST".getBytes();
        // 預先分配一個1MB的緩衝區
        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
        // 將字節數組中的數據複製到緩衝區中
        writeBuffer.put(req);
        // 進行flip操作,爲後續從緩衝區讀取數據做準備
        writeBuffer.flip();
        // 進行異步寫
        // 第三個參數用於寫操作完成後的回調
        client.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                // 如果發送緩衝區中仍有尚未發送的字節,將繼續異步發送
                if (attachment.hasRemaining()){
                    client.write(attachment, attachment, this);
                }else {
                    // 發送完成,進行異步的讀取操作
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    // 異步讀取服務端的響應消息,該操作是異步操作
                    client.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                        @Override
                        public void completed(Integer result, ByteBuffer attachment) {
                            // 進行flip操作,爲後續從緩衝區讀取數據做準備
                            attachment.flip();
                            // 根據緩衝區可讀的字節數創建字節數組
                            byte[] bytes = new byte[attachment.remaining()];
                            // 將緩衝區的可讀的字節數組複製到新創建的字節數組中
                            attachment.get(bytes);
                            String body;
                            try {
                                // 將讀取到的數據進行轉碼並打印
                                body = new String(bytes, "utf-8");
                                System.out.println("服務端返回的響應時間:" + body);
                                // 如果當前計數大於零,則其遞減。如果新的計數爲零,那麼所有等待的線程都將重新啓用,以用於線程調度目的。
                                latch.countDown();
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }

                        /**
                         * 讀取發生異常,關閉鏈路,同時調用countDown方法,讓AIOTimeServerHandler
                         * 執行完畢,客戶端退出執行
                         */
                        @Override
                        public void failed(Throwable exc, ByteBuffer attachment) {
                            try {
                                client.close();
                                latch.countDown();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                try {
                    client.close();
                    latch.countDown();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }

    @Override
    public void failed(Throwable exc, AIOTimeClientHandler attachment) {
        exc.printStackTrace();

        try {
            client.close();
            latch.countDown();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【1】AIO入門案例服務端的代碼具體實現以及詳細註釋
https://blog.csdn.net/wildwolf_001/article/details/81102982
【2】NIO入門案例使用netty最新版本框架代碼實現及詳細註釋
https://blog.csdn.net/wildwolf_001/article/details/81132896
【3】NIO入門案例客戶端的代碼具體實現以及詳細註釋
https://blog.csdn.net/wildwolf_001/article/details/81102953
【4】NIO入門案例之分析NIO服務端序列圖
https://blog.csdn.net/wildwolf_001/article/details/81069180

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章