首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java NIO 服务端开发实战:Buffer、Channel、Selector 三大核心组件与单线程多路复用模型

     編輯:Java 綜合教學

Java NIO 服务端开发实战

NIO(New IO / Non-blocking IO)基于 Buffer、Channel、Selector 三大核心,实现单线程处理成千上万连接。本文详解组件原理、文件 Channel 操作、服务端完整代码、Telnet 验证。

三大核心组件

Buffer 继承体系 Reactor 模型

文件 Channel 操作示例

// 写文件
FileChannel fc = new RandomAccessFile("nio-data.txt", "rw").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
buf.put("hi123".getBytes());
buf.flip();
fc.write(buf);

// 读文件
FileChannel fc = new FileInputStream("nio-data.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
while (fc.read(buf) != -1) {
    buf.flip();
    while (buf.hasRemaining()) System.out.print((char) buf.get());
    buf.clear();
}

// 文件拷贝
FileChannel in = new FileInputStream("in.txt").getChannel();
FileChannel out = new FileOutputStream("out.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
while (in.read(buf) != -1) {
    buf.flip();
    out.write(buf);
    buf.clear();
}

NIO 服务端完整实现(单线程 Reactor)

public class NioServer {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.socket().bind(new InetSocketAddress(8080));

        Selector selector = Selector.open();
        ssc.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            selector.select();  // 阻塞等待就绪事件
            Set keys = selector.selectedKeys();
            Iterator it = keys.iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();

                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_WRITE); // 直接注册写,演示发送
                } else if (key.isWritable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buf = ByteBuffer.wrap("hello".getBytes());
                    client.write(buf);
                    key.cancel(); // 发完即关闭
                }
            }
        }
    }
}

Telnet 验证

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
Connection closed by foreign host.

Telnet 多客户端 服务端输出

生产级扩展点

  1. 读事件处理:注册 OP_READ,循环 read() 直到返回 0 或 -1,组装完整消息
  2. 编解码器:LengthFieldBasedFrameDecoder + 自定义编解码,解决粘包/拆包
  3. 业务线程池:耗时业务提交 ExecutorService,Reactor 线程仅负责 IO
  4. Netty 框架:生产环境强烈建议直接用 Netty 4.x,封装了上述所有最佳实践

参考资料

《Netty 权威指南》(李林峰著)

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
组件角色关键点
Buffer数据容器本质是数组(ByteBuffer 最常用),维护 position/limit/capacity,flip() 切读写模式,clear() 重置
Channel双向通道网络:ServerSocketChannel/SocketChannel(可非阻塞);文件:FileChannel(仅阻塞)
Selector多路复用器单线程轮询就绪 Channel(OP_ACCEPT/OP_READ/OP_WRITE),JDK 用 epoll 替代 select,无 1024 句柄限制