更新時(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é)和異常處理。