网络编程基础:从BIO到NIO再到AIO(三)

BIO、NIO、AIO Java BIO 就是传统的 java io 编程,其相关的类和接口在 java.ioBIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器).​ 在上述的案例中,一个服务端只能接收一个客户端的通信请求,那么如果服务端需要处理很多个客户端的消息通信请求应该如何处理呢​ 在上述案例中:客户端的并发访问增加时。 阅读详情

AIO 核心概念讲解

一、AIO 是什么?

AIO = Asynchronous IO(异步 IO)

与 BIO、NIO 的架构对比:

AIO(异步式):
┌──────────────┐                    ┌──────────────┐
│   Server     │                    │   Client 1   │
│              │◀───Channel 1───────│              │
│              │                    └──────────────┘
│  系统线程池  │        ↓
│  (自动管理)  │    异步回调通知                    
│              │                    ┌──────────────┐
│CompletionHandler◀──Channel 2───────│   Client 2   │
│  (回调处理)  │                    └──────────────┘
│              │        ↓
│  操作完成后  │    异步回调通知
│  自动通知    │                    ┌──────────────┐
│              │◀───Channel 3───────│   Client 3   │
└──────────────┘                    └──────────────┘
                       ↓
                   异步回调通知

核心:操作完成后,系统主动通知你(打电话通知)

AIO 的核心特点:

  1. 异步:调用方法后立即返回,操作在后台进行
  2. 回调机制:操作完成后,系统自动调用回调函数
  3. 无需轮询:不需要像 NIO 那样用 Selector 轮询
  4. 系统管理线程:线程由系统管理,不需要自己创建

二、AIO 的核心组件

1. AsynchronousServerSocketChannel(异步服务端通道)

作用: 接受客户端连接

与 BIO/NIO 对比:

BIONIOAIO
ServerSocketServerSocketChannelAsynchronousServerSocketChannel
阻塞非阻塞(需轮询)异步(回调)
// 创建
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();

// 绑定端口
server.bind(new InetSocketAddress(7397));

// 接受连接(异步)
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
    @Override
    public void completed(AsynchronousSocketChannel client, Object attachment) {
        // 连接成功,自动调用这个方法
        // 重要:继续接受下一个连接
        server.accept(null, this);
    }
    
    @Override
    public void failed(Throwable exc, Object attachment) {
        // 连接失败
    }
});

2. AsynchronousSocketChannel(异步客户端通道)

作用: 读写数据

与 BIO/NIO 对比:

BIONIOAIO
SocketSocketChannelAsynchronousSocketChannel
阻塞非阻塞异步
// 创建
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();

// 连接(异步)
client.connect(new InetSocketAddress("127.0.0.1", 7397), null, 
    new CompletionHandler<Void, Object>() {
    @Override
    public void completed(Void result, Object attachment) {
        // 连接成功
    }
});

// 读取(异步)
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
    @Override
    public void completed(Integer bytesRead, ByteBuffer attachment) {
        // 读取成功
    }
});

// 写入(异步)
ByteBuffer buffer = ByteBuffer.wrap("hello".getBytes());
client.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
    @Override
    public void completed(Integer bytesWritten, ByteBuffer attachment) {
        // 写入成功
    }
});

3. CompletionHandler(完成处理器)

作用: 回调接口,操作完成后自动调用

这是 AIO 的核心!

// 泛型参数:
// - 第一个:操作结果类型
// - 第二个:附加对象类型

new CompletionHandler<Integer, ByteBuffer>() {
    /**
     * 操作成功时调用
     * @param result 操作结果(如读取的字节数)
     * @param attachment 附加对象(如缓冲区)
     */
    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        // 处理成功的情况
    }
    
    /**
     * 操作失败时调用
     * @param exc 异常信息
     * @param attachment 附加对象
     */
    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        // 处理失败的情况
    }
}

为什么需要 attachment(附加对象)?

// 问题:在回调中需要使用缓冲区,但回调是异步的
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, ???, handler);  // 怎么把 buffer 传给回调?

// 解决:通过 attachment 传递
channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        // attachment 就是传入的 buffer
        attachment.flip();
        // 可以使用 buffer 了
    }
});

4. ByteBuffer(字节缓冲区)

作用: 数据容器(与 NIO 相同)


三、SimpleAioServer 详解

类的作用:

使用 AIO 实现的服务端,异步处理客户端连接和消息。

核心流程图:

SimpleAioServer 启动流程:

1. 创建 AsynchronousServerSocketChannel
   ↓
2. 绑定端口 7397
   ↓
3. 调用 accept() 接受连接(异步)
   ↓
4. 主线程 sleep(等待)
   ↓
   (后台线程处理连接)
   ↓
5. 客户端连接 → completed() 被调用
   ↓
6. 在 completed() 中:
   ├─ 再次调用 accept()(继续接受下一个连接)
   ├─ 发送欢迎消息
   └─ 调用 read() 读取数据(异步)
   ↓
7. 客户端发消息 → read 的 completed() 被调用
   ↓
8. 在 read 的 completed() 中:
   ├─ 处理消息
   ├─ 调用 write() 回复(异步)
   └─ 在 write 的 completed() 中:
       └─ 再次调用 read()(继续读取下一条消息)

核心代码解析:

public static void main(String[] args) throws IOException, InterruptedException {
    // ========== 步骤1-2:初始化 ==========
    // 1. 创建异步服务端通道
    AsynchronousServerSocketChannel serverChannel = 
        AsynchronousServerSocketChannel.open();
    
    // 2. 绑定端口
    serverChannel.bind(new InetSocketAddress(7397));
    
    System.out.println("AIO 服务端启动,监听端口 7397...");
    
    // ========== 步骤3:接受连接(异步)==========
    
    // 参数1:附加对象(这里不需要,传 null)
    // 参数2:回调处理器
    serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
        
        /**
         * 连接成功时,系统自动调用这个方法
         * 
         * @param clientChannel 客户端通道
         * @param attachment 附加对象(这里是 null)
         */
        @Override
        public void completed(AsynchronousSocketChannel clientChannel, Object attachment) {
            try {
                System.out.println("新客户端连接:" + clientChannel.getRemoteAddress());
                
                // 重要!继续接受下一个客户端连接
                // 因为 accept() 只接受一个连接
                // 要继续接受,必须再次调用
                serverChannel.accept(null, this);
                
                // 发送欢迎消息
                String welcome = "欢迎连接到 AIO 服务器!\n";
                ByteBuffer welcomeBuffer = ByteBuffer.wrap(
                    welcome.getBytes(StandardCharsets.UTF_8)
                );
                clientChannel.write(welcomeBuffer);
                
                // 读取客户端消息
                readMessage(clientChannel);
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 连接失败时调用
         */
        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("接受连接失败:" + exc.getMessage());
        }
    });
    
    // ========== 步骤4:主线程等待 ==========
    
    // 为什么要 sleep?
    // 因为 AIO 是异步的,操作在后台线程执行
    // 如果主线程退出,程序就结束了
    Thread.sleep(Long.MAX_VALUE);
}

读取消息的实现:

private static void readMessage(AsynchronousSocketChannel clientChannel) {
    // 创建缓冲区
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    
    // 异步读取数据
    // 参数1:缓冲区(数据读到这里)
    // 参数2:附加对象(传递 buffer,方便在回调中使用)
    // 参数3:回调处理器
    clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
        
        /**
         * 读取成功时调用
         * 
         * @param bytesRead 读取的字节数
         * @param attachment 附加对象(这里是 buffer)
         */
        @Override
        public void completed(Integer bytesRead, ByteBuffer attachment) {
            try {
                if (bytesRead == -1) {
                    // 客户端断开
                    System.out.println("客户端断开:" + clientChannel.getRemoteAddress());
                    clientChannel.close();
                    return;
                }
                
                // 切换为读模式
                attachment.flip();
                
                // 读取数据
                byte[] bytes = new byte[attachment.remaining()];
                attachment.get(bytes);
                String message = new String(bytes, StandardCharsets.UTF_8).trim();
                
                System.out.println("收到消息:" + message);
                
                // 回复客户端
                String response = "服务端已收到:" + message + "\n";
                ByteBuffer responseBuffer = ByteBuffer.wrap(
                    response.getBytes(StandardCharsets.UTF_8)
                );
                
                // 异步写入
                clientChannel.write(responseBuffer, responseBuffer, 
                    new CompletionHandler<Integer, ByteBuffer>() {
                    
                    @Override
                    public void completed(Integer result, ByteBuffer attachment) {
                        // 写入完成
                        if ("bye".equalsIgnoreCase(message)) {
                            try {
                                System.out.println("客户端主动断开:" + 
                                    clientChannel.getRemoteAddress());
                                clientChannel.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        } else {
                            // 继续读取下一条消息
                            readMessage(clientChannel);
                        }
                    }
                    
                    @Override
                    public void failed(Throwable exc, ByteBuffer attachment) {
                        System.out.println("写入失败:" + exc.getMessage());
                    }
                });
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 读取失败时调用
         */
        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            System.out.println("读取失败:" + exc.getMessage());
            try {
                clientChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}

关键点:

  1. accept() 只接受一个连接:必须在 completed() 中再次调用
  2. 异步操作立即返回:不会阻塞线程
  3. 回调嵌套:读取 → 写入 → 读取(容易形成回调地狱)
  4. 主线程要等待:否则程序会立即退出

四、SimpleAioClient 详解

类的作用:

使用 AIO 实现的客户端,异步连接服务端并收发消息。

核心流程图:

SimpleAioClient 启动流程:

1. 创建 AsynchronousSocketChannel
   ↓
2. 调用 connect() 连接服务端(异步)
   ↓
3. 主线程 sleep(等待)
   ↓
   (后台线程处理连接)
   ↓
4. 连接成功 → completed() 被调用
   ↓
5. 在 completed() 中:
   ├─ 调用 read() 读取服务端消息(异步)
   └─ 启动用户输入线程
   ↓
6. 服务端发消息 → read 的 completed() 被调用
   ├─ 打印消息
   └─ 再次调用 read()(继续读取)
   ↓
7. 用户输入 → 调用 write() 发送(异步)

核心代码解析:

public static void main(String[] args) throws IOException, InterruptedException {
    // 1. 创建异步客户端通道
    clientChannel = AsynchronousSocketChannel.open();
    
    // 2. 连接服务端(异步)
    clientChannel.connect(new InetSocketAddress("127.0.0.1", 7397), null, 
        new CompletionHandler<Void, Object>() {
        
        /**
         * 连接成功时调用
         */
        @Override
        public void completed(Void result, Object attachment) {
            System.out.println("已连接到服务端");
            
            // 读取服务端的欢迎消息
            readMessage();
            
            // 启动用户输入线程
            startInputThread();
        }
        
        /**
         * 连接失败时调用
         */
        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("连接失败:" + exc.getMessage());
        }
    });
    
    // 3. 主线程等待
    Thread.sleep(Long.MAX_VALUE);
}

读取消息的实现:

private static void readMessage() {
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    
    // 异步读取
    clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
        
        @Override
        public void completed(Integer bytesRead, ByteBuffer attachment) {
            if (bytesRead == -1) {
                // 服务端断开
                System.out.println("服务端断开连接");
                System.exit(0);
                return;
            }
            
            // 切换为读模式
            attachment.flip();
            
            // 读取数据
            byte[] bytes = new byte[attachment.remaining()];
            attachment.get(bytes);
            String message = new String(bytes, StandardCharsets.UTF_8).trim();
            
            System.out.println("服务端回复:" + message);
            
            // 继续读取下一条消息
            readMessage();
        }
        
        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            System.out.println("读取失败:" + exc.getMessage());
        }
    });
}

发送消息的实现:

private static void sendMessage(String message) {
    ByteBuffer buffer = ByteBuffer.wrap(
        (message + "\n").getBytes(StandardCharsets.UTF_8)
    );
    
    // 异步写入
    clientChannel.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
        
        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            // 写入完成
        }
        
        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            System.out.println("发送失败:" + exc.getMessage());
        }
    });
}

五、BIO vs NIO vs AIO 完整对比

代码对比:

BIO(阻塞式):

// 服务端
ServerSocket server = new ServerSocket(7397);
while (true) {
    Socket socket = server.accept();  // 阻塞
    new Thread(() -> {
        String msg = reader.readLine();  // 阻塞
    }).start();
}

NIO(非阻塞式):

// 服务端
Selector selector = Selector.open();
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
    selector.select();  // 阻塞,但监控多个通道
    for (SelectionKey key : selector.selectedKeys()) {
        if (key.isAcceptable()) { /* 接受连接 */ }
        if (key.isReadable()) { /* 读取数据 */ }
    }
}

AIO(异步式):

// 服务端
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(7397));
server.accept(null, new CompletionHandler<>() {
    public void completed(AsynchronousSocketChannel client, Object attachment) {
        server.accept(null, this);  // 继续接受
        client.read(buffer, buffer, readHandler);  // 异步读取
    }
});
Thread.sleep(Long.MAX_VALUE);  // 等待

六、AIO 代码示例

/**
 * 最简单的 AIO 服务端
 * 
 * AIO 核心:异步 + 回调
 * 操作完成后,系统自动调用回调函数
 */
public class SimpleAioServer {

    public static void main(String[] args) throws IOException, InterruptedException {
        // 1. 创建异步服务端通道
        AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();
        // 2. 绑定端口
        serverChannel.bind(new InetSocketAddress(7397));
        System.out.println("AIO 服务端启动,监听端口 7397...");
        // 3. 接受连接(异步)
        serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
            @Override
            public void completed(AsynchronousSocketChannel clientChannel, Object attachment) {
                try {
                    System.out.println("新客户端连接:" + clientChannel.getRemoteAddress());
                    // 重要!继续接受下一个客户端连接
                    serverChannel.accept(null, this);
                    // 发送欢迎消息
                    String welcome = "欢迎连接到 AIO 服务器!\n";
                    ByteBuffer welcomeBuffer = ByteBuffer.wrap(welcome.getBytes(StandardCharsets.UTF_8));
                    clientChannel.write(welcomeBuffer);
                    // 读取客户端消息
                    readMessage(clientChannel);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void failed(Throwable exc, Object attachment) {
                System.out.println("接受连接失败:" + exc.getMessage());
            }
        });
        // 4. 主线程等待(因为 AIO 是异步的,操作在后台线程执行)
        Thread.sleep(Long.MAX_VALUE);
    }
    
    /**
     * 读取客户端消息
     */
    private static void readMessage(AsynchronousSocketChannel clientChannel) {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 异步读取数据
        clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer bytesRead, ByteBuffer attachment) {
                try {
                    if (bytesRead == -1) {
                        System.out.println("客户端断开:" + clientChannel.getRemoteAddress());
                        clientChannel.close();
                        return;
                    }
                    // 切换为读模式
                    attachment.flip();
                    // 读取数据
                    byte[] bytes = new byte[attachment.remaining()];
                    attachment.get(bytes);
                    String message = new String(bytes, StandardCharsets.UTF_8).trim();
                    System.out.println("收到消息:" + message);
                    // 回复客户端
                    String response = "服务端已收到:" + message + "\n";
                    ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes(StandardCharsets.UTF_8));
                    // 异步写入
                    clientChannel.write(responseBuffer, responseBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                        @Override
                        public void completed(Integer result, ByteBuffer attachment) {
                            if ("bye".equalsIgnoreCase(message)) {
                                try {
                                    System.out.println("客户端主动断开:" + clientChannel.getRemoteAddress());
                                    clientChannel.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            } else {
                                // 继续读取下一条消息
                                readMessage(clientChannel);
                            }
                        }
                        @Override
                        public void failed(Throwable exc, ByteBuffer attachment) {
                            System.out.println("写入失败:" + exc.getMessage());
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("读取失败:" + exc.getMessage());
                try {
                    clientChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
/**
 * 最简单的 AIO 客户端
 * 
 * 功能:连接服务端,发送消息,接收回复
 */
public class SimpleAioClient {

    private static AsynchronousSocketChannel clientChannel;

    public static void main(String[] args) throws IOException, InterruptedException {
        // 1. 创建异步客户端通道
        clientChannel = AsynchronousSocketChannel.open();
        // 2. 连接服务端(异步)
        clientChannel.connect(new InetSocketAddress("127.0.0.1", 7397), null, 
            new CompletionHandler<Void, Object>() {
            @Override
            public void completed(Void result, Object attachment) {
                System.out.println("已连接到服务端");
                // 读取服务端的欢迎消息
                readMessage();
                // 启动用户输入线程
                startInputThread();
            }
            @Override
            public void failed(Throwable exc, Object attachment) {
                System.out.println("连接失败:" + exc.getMessage());
            }
        });
        // 3. 主线程等待
        Thread.sleep(Long.MAX_VALUE);
    }
    
    /**
     * 读取服务端消息
     */
    private static void readMessage() {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer bytesRead, ByteBuffer attachment) {
                if (bytesRead == -1) {
                    System.out.println("服务端断开连接");
                    System.exit(0);
                    return;
                }
                // 切换为读模式
                attachment.flip();
                // 读取数据
                byte[] bytes = new byte[attachment.remaining()];
                attachment.get(bytes);
                String message = new String(bytes, StandardCharsets.UTF_8).trim();
                System.out.println("服务端回复:" + message);
                // 继续读取下一条消息
                readMessage();
            }
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("读取失败:" + exc.getMessage());
            }
        });
    }
    
    /**
     * 启动用户输入线程
     */
    private static void startInputThread() {
        new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入消息(输入 bye 退出):");
            while (scanner.hasNextLine()) {
                String input = scanner.nextLine();
                sendMessage(input);
                if ("bye".equalsIgnoreCase(input)) {
                    try {
                        Thread.sleep(1000);
                        System.exit(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    
    /**
     * 发送消息
     */
    private static void sendMessage(String message) {
        ByteBuffer buffer = ByteBuffer.wrap((message + "\n").getBytes(StandardCharsets.UTF_8));
        clientChannel.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                // 写入完成
            }
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                System.out.println("发送失败:" + exc.getMessage());
            }
        });
    }
}

BIO,NIO,多路复用,AIO BIO,NIO,多路复用,AIO 概念理解 IO流程 三大IO模型的解释 总结 BIO,NIO,多路复用,AIO 概念理解 同步和异步 关注点在于处理机制,同步在于等待上一条语句调用后的返回结果才继续,异步在于事件响应回调机制,语句调用后直接返回,等触发事件之后,自动调用写好的回调函数 阻塞非阻塞 关注点在于线程是否挂起 阻塞在于得到结果之前会挂起线程,非阻塞在于不会... 阅读详情

相关推荐

Netty(一)——BIO、NIO、AIO

         在工作中,无论什么项目我们都会用到网络传输,tomcat等server服务器、Dubbo等Rpc协议框架、Redis等NOsql数据库、各种MQ的中间件等等。这篇文章是学习《Netty权威指南》后的总结,从Java基础的BIO、NIO、AIO进行学习。         在说JavaIO以前,先看看unix提供的5种IO模型:         1,阻塞IO模型:    ...

学会改变自己——才能突破 1311

Java IO与NIO零基础详解:BIO_NIO_AIO区别、多路复用实战

本文全面介绍了Java中的三大IO模型:BIO、NIO和AIO。文章从零基础概念入手,通过生活类比解释阻塞/非阻塞、同步/异步等核心概念,重点讲解了多路复用机制。针对每种IO模型,作者提供了完整可运行的代码示例,包括BIO的单线程和多线程实现、NIO的多路复用实战,以及Windows平台的AIO适配方案。通过场景化对比分析,帮助开发者理解不同IO模型的适用场景和选型策略,掌握高并发IO编程的核心技术。文章特别适合Java初学者和需要深入理解IO模型的开发者阅读。

网络工程师|十多年企业级运维实战|精通 ‌BGP、OSPF、VLAN、SDN、MPLS、ACL、NetFlow、SNMP、 542

NU1680无线充电接收器在TWS耳机中的应用实战:I2C调压与QI协议适配

本文详细解析了NU1680无线充电接收器在TWS耳机充电仓设计中的应用实战。重点阐述了其无固件设计、I2C接口动态调压功能如何解决不同QI协议发射器的兼容性难题,并分享了硬件设计、PCB布局、与发射端联调及安全测试等关键环节的实践经验,助力开发者快速实现稳定高效的无线充电方案。

weixin_28432777的博客 233

网络编程入门

本文介绍了网络编程的基础概念,主要包括:1)OSI七层模型的分层结构和各层功能;2)三种主流通信框架(C/S、B/S、P2P)的特点与应用场景;3)Java中的三种IO模型(BIO、NIO、AIO)的工作原理及优缺点;4)IP地址和端口的作用与分类,重点说明了IPv4/IPv6的区别及端口号范围划分。这些基础知识构成了网络编程的核心框架,为理解设备间通信原理和开发网络应用奠定了基础。

2401_87353928的博客 603

别再到处找包了!Keil5芯片支持包(Pack)最全管理指南:安装、更新、迁移与离线备份

本文详细解析了Keil5芯片支持包(Pack)的全生命周期管理,包括安装、更新、迁移与离线备份的工程化解决方案。针对STM32F10x等常见芯片,提供了高效获取Pack的策略、版本管理技巧及团队协作方案,帮助开发者解决常见的'Device Family Pack missing'等问题,提升嵌入式开发效率。

weixin_28729205的博客 542

Windows 10/11系统下TurboDesign 6.4.0完整安装指南(附序列号+破解补丁)

本文提供Windows 10/11系统下TurboDesign 6.4.0的完整安装指南,涵盖系统环境预检、安装程序部署、序列号处理及破解补丁部署等关键步骤。通过详细的安装教程和优化配置,帮助用户高效完成这款涡轮机械设计软件的安装与调试,解决常见兼容性问题。

s4t5u6v的博客 1031

BIO、NIO、AIO详解

一、Java的I/O演进之路 Java共支持3种网络编程的I/O模型:BIO、NIO、AIO BIO: 同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销 NIO: 同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理 AIO: 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求

hxt的博客 2万+

Ansys Zemax|无焦系统设计中的角度单位优化技巧

本文详细介绍了在Ansys Zemax OpticStudio中进行无焦系统设计的核心技巧。重点阐述了从聚焦思维到角度思维的转换,并演示了如何通过开启‘无焦像空间’模式、构建以波前和光束尺寸为目标的评价函数来优化激光扩束镜等系统。文章还分享了使用IMSF操作数处理混合系统以及常见误区避坑的实用指南,旨在帮助光学设计者高效完成无焦系统的设计与分析。

weixin_29231027的博客 362

面试官:BIO、NIO、AIO是什么,他们有什么区别?

面试官:BIO、NIO、AIO是什么,他们有什么区别?

真正的大师永远怀着一颗学徒的心 9948

Open3D 点云数学形态学滤波(Python版本)

Open3D 点云数学形态学滤波(Python版本)

dayuhaitang1的博客 1397

IgH EtherCAT 从入门到精通:第 30 章 实战:高可用 EtherCAT 系统设计

摘要:构建高可用EtherCAT系统的关键技术 本章详细介绍了工业级EtherCAT系统的高可用性设计方法,主要包括: 冗余链路架构:采用双网卡环形拓扑设计,主备网卡同时工作,通过IgH Master的冗余配置实现线缆故障自动切换。 状态监控机制:提供专用API实时监控主备链路状态,包括从站响应数、链路状态和冗余激活标志,形成完整的故障判断矩阵。 自动恢复功能:系统内置FSM架构支持热插拔自动检测和重配置,从站断线/重连时可自动完成状态恢复,同时允许应用层实施安全措施。 这些技术共同构成了生产环境下Ethe

从事嵌入式linux android驱动开发,拥有全栈能力 247

BIO、NIO、AIO 有什么区别?

BIO、NIO、AIO 有什么区别? BIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。 NIO:线程发起IO请求,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调函数通知线程做IO操作,线程开始阻塞,直到操作完成。 AIO:线程发起IO请求,立即返回;内存做好IO操作的准备之后,做IO操作,直到操作完成或者失败,通过调用注册的回调...

ConstXiong 2万+

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

weixin_74013772的博客 256

BIO,NIO,AIO的区别

BIO,NIO和AIO是Java网络编程的三种模型 BIO:同步并阻塞,服务实现模式为一个连接对应一个线程,即客户端发送一个连接,服务端要有一个线程来处理。如果连接多了,线程数量不够,就只能等待,即会发生阻塞。 NIO:同步非阻塞,服务实现模式是一个线程可以处理多个连接,即客户端发送的连接都会注册到多路复用器上,然后进行轮询连接,有I/O请求就处理 AIO:异步非阻塞,引入了异步通道,采用的是proactor模式,特点是:有效的请求才启动线程,先有操作系统完成在通知服务端 应用场景: BIO:

qxy_1218的博客 1万+

【红绿灯识别】基于计算机视觉实现道路信号灯检测识别系统附Matlab代码

随着自动驾驶技术的快速发展,对道路交通信号灯的检测识别技术也提出了更高的要求。本文提出了一种基于计算机视觉的道路信号灯检测识别系统,该系统能够准确地检测和识别道路交通信号灯,并输出信号灯的颜色信息。该系统采用深度学习方法,利用卷积神经网络(CNN)对道路交通信号灯进行检测和识别。实验结果表明,该系统能够在复杂的环境中准确地检测和识别道路交通信号灯,具有较高的实用价值。道路交通信号灯是道路交通管理的重要组成部分,它能够有效地组织交通,提高道路通行效率,保障交通安全。

qq_59747472的博客 341

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

AIO,BIO,NIO详解

一、基本概念 IO:阻塞IO BIO:同步阻塞IO。服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器需要启动一个线程进行处理,如果这个链接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 NIO:同步非阻塞IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。用户进程也需要时不时的询...

不务正业随手记 6737

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

一文搞懂Java BIO、NIO、AIO的核心区别

简单应用、低并发场景,选 BIO 足够,编程成本低;高并发网络编程场景,选 NIO,多路复用能大幅提升性能;高并发且 IO 操作耗时较长的场景,选 AIO,异步通知能最大化利用线程资源。掌握这三种 IO 模型的核心区别,能帮助我们在实际开发中做出更合理的技术选型,写出更高效的 Java 程序。

2301_79892101的博客 2358

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

BIO、NIO与AIO

I/O 模型:就是用什么样的通道或者说是通信模式和架构进行数据的传输和接收,很大程度上决定了程序通信的性能,Java 共支持 3 种网络编程的/IO 模型:**BIO、NIO、AIO** 1 每当接收到一个Socket连接就会创建一个新的线程,线程的竞争以及上下文切换会影响性能;2 每个线程都会占用栈空间和CPU资源;3 并不是每个socket都进行IO操作,无意义的线程处理(即使客户端没有消息,服务端的线程也会阻塞等待);

weixin_42828342的博客 1718

JAVAIO模型之NIO、BIO、AIO

IO模型 io模型就是各种数据使用相应通道进行发送和接收。Java共支持三种网络编程IO模式 BIO、NIO、AIO BIO (Blocking IO) 同步阻塞模型,一个客户端连接对应一个处理线程。 缺点 IO代码里read是阻塞操作,如果连接不做读写操作会导致线程阻塞,浪费资源 如果读写很多,会导致服务器线程过多,压力太大。 应用场景 BIO适用于连接数目较小且固定的架构,这种方式对服务器资源的要求比较高,但是程序简单易理解。 示例代码 /** * 服务端 * @author 风信子 */

Zev_java的博客 1421

Java IO 模型之 BIO、NIO、AIO 详解

在 Java 编程中,IO(Input/Output)操作是非常常见的操作,它涉及到文件读写、网络通信等方面。Java 提供了各种类来支持这些操作。本文将从 IO 的基础知识讲起,逐步深入,介绍 Java IO 的各个方面。Java IO(Input/Output)是 Java 语言中用于读写数据的 API,它提供了一系列类和接口,用于读取和写入各种类型的数据。

流华追梦的专栏 2117

详解BIO,NIO,AIO

详解BIO,NIO,AIO

m0_66220639的博客 1258

面试官:BIO、NIO、AIO 的区别是什么?

这是个网络编程的面试题:在讲 BIO,NIO,AIO 之前先来回顾一下这样几个概念:同步与异步,阻塞与非阻塞。自己的理解:也就是必须一件一件事做,等前一件做完了才能做下一件事 (提交请求->等待服务器处理->处理完返回 这个期间客户端浏览器不能干任何事 )官方:使用同步IO时,Java自己处理IO读写。

2401_85910670的博客 1147

Java的BIO、NIO、AIO模型

NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,编程比较复杂, JDK1.4 开始支持。2、channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理。同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到。1、IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源。同步阻塞模型,一个客户端连接对应一个处理线程。

weixin_42037190的博客 1048

BIO、NIO、AIO的区别?

Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。

西京刀客 1255
上一篇: 网络编程基础:从BIO到NIO再到AIO(二)
下一篇: 网络编程基础:从BIO到NIO再到AIO(四)
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值