AIO异步非阻塞网络编程
AIO 的全称是 asynchronized IO,是从 JDK 7 开始支持的。AIO 不是在 IO 准备好时再通知线程的,而是在 IO 操作已经完成后,再给线程发出通知的。因此,AIO 是完全不会阻塞的。AIO 的特点如下:
-
读完了再通知线程。
-
不会加快 IO,只是在读完后进行通知。
-
使用回调函数,进行业务处理。
AIO 需要使用异步通道,即 AsynchronousServerSocketChannel。其中,accept() 方法主要负责两件事:一件事是发起 accept 请求,告诉系统可以开始监听端口了;另一件事是注册 CompletionHandler 实例,当有客户端进行连接时:如果连接成功,就执行 CompletionHandler.completed() 方法;如果连接失败,就执行 CompletionHandler.failed() 方法。因此,accept() 方法不会被阻塞。
下面使用 AIO 分别编码实现客户端和服务器端。客户端的代码如下:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;
public class SimpleAIOClient {
static final int PORT = 9000;
public static void main(String[] args) throws Exception {
// 用于读取数据的 ByteBuffer
ByteBuffer bba = ByteBuffer.allocate(1024);
Charset ctf = Charset.forName("utf-8");
try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
// 连接远程服务器
asc.connect(new InetSocketAddress("127.0.0.1", PORT)).get();
bba.clear();
// 从 clientChannel 中读取数据
asc.read(bba).get();
bba.flip();
// 将 buff 中内容转换为字符串
String str = ctf.decode(bba).toString();
System.out.println("由服务器端发送的信息:" + str);
}
}
}
服务器端的代码如下:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.Future;
public class SimpleAIOServer {
static final int PORT = 9000;
public static void main(String[] args) throws Exception {
try (AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open()) {
// 在指定的地址、端口处进行监听
assc.bind(new InetSocketAddress(PORT));
while (true) {
// 采用循环接受来自客户端的连接
Future<AsynchronousSocketChannel> ft = assc.accept();
// 获取连接完成后返回的 AsynchronousSocketChannel
AsynchronousSocketChannel asc = ft.get();
// 执行输出
asc.write(ByteBuffer.wrap("你好!".getBytes("UTF-8"))).get();
}
}
}
}
先运行服务器端,再运行客户端。运行结果如下:
由服务器端发送的信息:你好!