Java 中的 Socket 通信是基于阻塞式的 IO 模型實現的。這種模型會導致客戶端一次只能與服務器端建立一次連接,而一旦連接建立成功,客戶端和服務器端之間的通信便是阻塞式的。
對于如此低效的通信方式,Java 提供了兩種新型的 IO 模型:AIO 和 NIO。這兩種模型的主要區別在于處理 I/O 操作的方式不同。AIO 是異步非阻塞 I/O,而 NIO 是同步非阻塞 I/O。
AIO AsynchronousSocketChannel server = AsynchronousSocketChannel.open().bind(new InetSocketAddress(PORT)); CompletionHandlerhandler = new CompletionHandler () { @Override public void completed(AsynchronousSocketChannel channel, Object attachment) { // 處理連接請求 server.accept(null, this); // 處理消息 ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer, null, new CompletionHandler () { @Override public void completed(Integer result, Object attachment) { // 處理接收到的消息 } @Override public void failed(Throwable exc, Object attachment) { // 處理異常 } }); } @Override public void failed(Throwable exc, Object attachment) { // 處理異常 } }; server.accept(null, handler);
NIO 的實現主要依賴于 Channel 和 Buffer 兩個核心抽象。Channel 用于數據的讀寫操作,而 Buffer 則用于數據的緩存。從根本上講,NIO 的非阻塞模式與傳統的阻塞式 I/O 模式十分相似。
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); InetSocketAddress address = new InetSocketAddress(PORT); serverSocketChannel.socket().bind(address); Selector selector = Selector.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while(true){ if(selector.selectNow() == 0){ continue; } SetselectedKeys = selector.selectedKeys(); Iterator iterator = selectedKeys.iterator(); while(iterator.hasNext()){ SelectionKey key = iterator.next(); if(key.isAcceptable()){ // 處理連接請求 }else if(key.isReadable()){ // 處理消息 ByteBuffer buffer = ByteBuffer.allocate(1024); SocketChannel channel = (SocketChannel) key.channel(); channel.read(buffer); // 對接收到的消息進行解析 } iterator.remove(); } }
綜上所述,無論是 AIO 還是 NIO,它們都是為了解決代碼阻塞問題而誕生的,能夠提高程序的運行效率和穩定性。