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