更新時(shí)間:2023-03-22 來(lái)源:黑馬程序員 瀏覽量:
BIO、NIO、AIO 都是 Java 中用于實(shí)現(xiàn)網(wǎng)絡(luò)編程的三種不同的方式,它們有以下區(qū)別:
1.BIO (Blocking I/O):傳統(tǒng)的阻塞式 I/O,每個(gè)連接都需要一個(gè)線程來(lái)處理,當(dāng)連接數(shù)較多時(shí),會(huì)導(dǎo)致系統(tǒng)資源消耗嚴(yán)重,性能較差。
2.NIO (Non-blocking I/O):非阻塞式 I/O,通過(guò)使用單線程輪詢多個(gè)連接的方式來(lái)實(shí)現(xiàn)高效的處理方式,可以支持較大數(shù)量的并發(fā)連接,但編程模型較為復(fù)雜。
3.AIO (Asynchronous I/O):異步 I/O,通過(guò)回調(diào)方式實(shí)現(xiàn)高效的 I/O 操作,可以大大降低系統(tǒng)資源的消耗,適用于高并發(fā)、高吞吐量的場(chǎng)景,但在實(shí)際使用中可能會(huì)受到操作系統(tǒng)和硬件的限制。
下面是 Java 中分別使用 BIO、NIO、AIO 實(shí)現(xiàn)簡(jiǎn)單的網(wǎng)絡(luò)通信的示例代碼:
BIO 示例代碼:
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class BioServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); while (true) { Socket socket = serverSocket.accept(); new Thread(() -> { try { InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } } }
NIO 示例代碼:
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; public class NioServer { private Selector selector; public static void main(String[] args) throws IOException { new NioServer().startServer(); } public void startServer() throws IOException { selector = Selector.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 8000)); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("Server started on port 8000..."); while (true) { selector.select(); Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { acceptConnection(key); } else if (key.isReadable()) { readFromClient(key); } keyIterator.remove(); } } } private void acceptConnection(SelectionKey key) throws IOException { ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); System.out.println("Connection accepted from client: " + socketChannel.getRemoteAddress()); } private void readFromClient(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = socketChannel.read(buffer); if (bytesRead == -1) { socketChannel.close(); System.out.println("Connection closed by client: " + socketChannel.getRemoteAddress()); } else { byte[] data = new byte[bytesRead]; buffer.flip(); buffer.get(data, 0, bytesRead); System.out.println("Received message from client: " + new String(data)); socketChannel.write(ByteBuffer.wrap("Hello from server".getBytes())); } } }
AIO 示例代碼:
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; public class AioServer { public static void main(String[] args) throws IOException { AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(8080)); serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() { @Override public void completed(AsynchronousSocketChannel result, Object attachment) { serverSocketChannel.accept(null, this); ByteBuffer buffer = ByteBuffer.allocate(1024); result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer buffer) { if (result > 0) { buffer.flip(); byte[] bytes = new byte[buffer.limit()]; buffer.get(bytes); System.out.println(new String(bytes)); buffer.clear(); result.write(ByteBuffer.wrap("Hello, client!".getBytes())); } else if (result == -1) { try { result.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { result.close(); } catch (IOException e) { e.printStackTrace(); } } }); } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); } }); while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
這些代碼僅作為簡(jiǎn)單的演示,實(shí)際應(yīng)用中需要考慮更多的細(xì)節(jié)和異常處理。