详细谈谈AIO、BIO、NIO 的区别

目录

一、什么是AIO

二、什么是BIO

三、什么是NIO

四、NIO 在 Netty 中的使用


一、什么是AIO

AIO(Asynchronous I/O,异步输入输出)是一种处理输入输出的编程模型,它允许同时处理多个输入输出操作,而不需要等待每个操作完成。在Python中,可以使用asyncio库来实现AIO编程。

下面是一个使用asyncio库简单示例代码:

import asyncio
​
async def hello():
    print("Hello")
    await asyncio.sleep(1)
    print("World")
​
async def main():
    await asyncio.gather(hello(), hello())
​
asyncio.run(main())

在这个示例中,hello函数是一个异步函数,它打印"",然后等待1秒钟,最后再打印"World"。main函数是另一个异步函数,它使用asyncio.gather方法同时运行两个hello任务。

通过asyncio.run(main())来运行main函数,它会创建一个事件循环并执行异任务。

运行上述代码,你会看到输出结果是交替打印的"Hello"和"World",而不是等待一个任务完成后再执行另一个任务。这就是AIO的特点,可以同时处理多个任务,提高程序的效率。

详细谈谈AIO、BIO、NIO 的区别_第1张图片

二、什么是BIO

BIO(BlockI/O,阻塞输入输出)是一种传统的输入输出模型,它在执行输入输出操作时会阻塞程序的执行,直到操作完成才会进行下一步。在Java中,可以使用java.net包中的SocketServerSocket类来实现BIO编程。下面是一个简单的Java示例代码:

Server端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
​
public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("Server started.");
​
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("Client connected.");
​
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
​
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) != -1) {
                    String message = new String(buffer, 0, length);
                    System.out.println("Received message: " + message);
​
                    outputStream.write(message.getBytes());
                    outputStream.flush();
                }
​
                socket.close();
                System.out.println("Client disconnected.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
​
public class Client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 8888);
            System.out.println("Connected to server.");
​
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
​
            String message = "Hello, server!";
            outputStream.write(message.getBytes());
            outputStream.flush();
​
            byte[] buffer = new byte[1024];
            int length = inputStream.read(buffer);
            String response = new String(buffer, 0, length);
            System.out.println("Received response: " + response);
​
            socket.close();
            System.out.println("Disconnected from server.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,Server端通过ServerSocket监听8888端口,当有Client连接时,会创建一个新的Socket来与Client进行通信。Server端使用InputStream来接收Client发送的消息,然后通过OutputStream发送响应消息给Client。Client端通过Socket连接到Server,并使用InputStream发送消息给Server,然后通过OutputStream接收Server的响应消息。

需要注意的是,BIO模型中的输入输出操作是阻塞的,也就是说当没有数据可读取或写入时,程序会一直阻塞在相应的读取或写入操作处,直到有数据或者操作完成才会继续执行。

详细谈谈AIO、BIO、NIO 的区别_第2张图片

 

三、什么是NIO

NIO(New IO)是Java中用于处理非阻塞I/O操作的API,它提供了一种更高效、更灵活的方式来进行网络编程。

下面是一个简单的Java NIO示例代码,展示了如何使用NIO进行文件复制操作:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
​
public class NIOFileCopyExample {
    public static void main(String[] args) {
        String sourceFilePath = "path/to/source/file";
        String destinationFilePath = "path/to/destination/file";
​
        try {
            // 创建输入流和流
            FileInputStream fis = new FileInputStream(sourceFilePath);
            FileOutputStream fos = new FileOutputStream(destinationFilePath);
​
            // 创建输入流和输出流的通道
            FileChannel inputChannel = fis.getChannel();
            FileChannel outputChannel = fos.getChannel();
​
            // 创建缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(1024);
​
            // 从输入通道取数据到缓冲区
            while (inputChannel.read(buffer) != -1) {
                buffer.flip(); // 切换为读模式
                // 从缓冲区写入数据到输出通道
                outputChannel.write(buffer);
                buffer.clear(); // 清空缓冲区
            }
​
            // 关闭通道和流
 inputChannel.close();
            outputChannel.close();
            fis.close();
            fos.close();
​
            System.out.println("文件复制完成!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

以上代码通过使用NIO的FileChannelByteBuffer,实现了从源文件复制数据到目标文件操作。需要注意的是,该示例中只是简单地进行文件复制,并未处理异常情况和完善错误处理。在实际应用中,可能需要进一步优化和处理相关逻辑。

详细谈谈AIO、BIO、NIO 的区别_第3张图片

 

四、NIO 在 Netty 中的使用

在Netty中,NIO被广泛用于构建高性能的网络应用程序。Netty封装了Java NIO API,并提供了一套更简洁、易用的抽象层,使得开发者能够更方便地使用NIO进行网络编程。

下面是一个简单的Netty使用NIO的示例代码,展示了如何创建一个简单的Echo服务器:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
​
public class EchoServer {
    private int port;
​
    public EchoServer(int port) {
        this.port = port;
    }
​
    public void start() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .option(ChannelOption.SO_BACKLOG, 128)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ChannelInitializer() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new StringEncoder(), new StringDecoder(), new EchoServerHandler());
                }
             });
            
            // 绑定端口,开始接收进来的连接
            b.bind(port).sync().channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
​
    public static void main(String[] args) throws Exception {
        int port = 8888;
        new EchoServer(port).start();
    }
}
​
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
​
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String message = (String) msg;
        System.out.println("Received message: " + message);
        ctx.write(message);
    }
​
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
​
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

以上代码创建了一个简单的Echo服务器,当客户端连接到服务器并发送消息时,服务器将原样将消息返回给客户端。在该示例中,NioEventLoopGroup用于处理I/O事件的多线程事件循环组,NioServerSocketChannel用于创建服务器端的通道,ChannelOption.SO_BACKLOG设置了服务器的最大连接数,LoggingHandler用于记录日志。EchoServerHandler类继承自ChannelInboundHandlerAdapter,用于处理接收到的消息。

这只是一个简单的示例,你可以根据实际需求,使用Netty的NIO功能进行更复杂的网络应用程序开发。

你可能感兴趣的:(Java学习,nio,python,网络)