【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!

简介: 【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。

Java NIO(Non-blocking I/O,非阻塞 I/O)是 Java 平台中用于处理大量并发连接的一种高效 I/O 模型。NIO 的引入极大地提高了 Java 应用程序在网络通信方面的性能。Netty 是一个基于 NIO 的高性能网络框架,它利用 Java NIO 的特性来构建可扩展的服务器和客户端应用。本文将以技术综述的形式,介绍 Java NIO 的基本概念,并通过示例代码展示如何使用 Java NIO 和 Netty 来开发网络应用。

Java NIO 基础

Java NIO 引入了几个核心组件:Buffer、Channel、Selector 和 SocketChannel。

  • Buffer:用于存储数据。Buffer 是一个容器,用于存放从 Channel 读取的数据或写入 Channel 的数据。
  • Channel:用于读写数据。Channel 是双向的,可以读也可以写。
  • Selector:用于监听多个 Channel 的 I/O 状态。Selector 可以监听 Channel 是否准备好读、写或连接等操作。
  • SocketChannel:用于网络通信。它是 Channel 的一个子类,专门用于处理 TCP/IP 连接。

Java NIO 示例代码

下面是一个简单的 Java NIO 服务器端和客户端的示例代码,用于演示如何使用 Java 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;
import java.util.Set;

public class NioServer {
   
    private static final int PORT = 8080;

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

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

        while (true) {
   
            selector.select();

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectedKeys.iterator();

            while (iterator.hasNext()) {
   
                SelectionKey key = iterator.next();

                if (key.isAcceptable()) {
   
                    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);
                    sc.register(selector, SelectionKey.OP_READ);
                }

                if (key.isReadable()) {
   
                    SocketChannel sc = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int read = sc.read(buffer);
                    if (read > 0) {
   
                        buffer.flip();
                        byte[] data = new byte[buffer.remaining()];
                        buffer.get(data);
                        System.out.println("Received from client: " + new String(data));
                    }
                }

                iterator.remove();
            }
        }
    }
}

客户端代码

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NioClient {
   
    private static final int PORT = 8080;
    private static final String HOST = "localhost";

    public static void main(String[] args) throws IOException {
   
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new java.net.InetSocketAddress(HOST, PORT));

        while (!socketChannel.finishConnect()) {
   
            // 等待连接完成
        }

        ByteBuffer buffer = ByteBuffer.wrap("Hello, Server!".getBytes());
        socketChannel.write(buffer);

        socketChannel.close();
    }
}

Netty 示例代码

Netty 是一个基于 NIO 的高性能网络框架,它简化了 Java NIO 的使用。下面是使用 Netty 构建一个简单的 TCP 服务器和客户端的示例。

服务器端代码

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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;

public class NettyServer {
   
    private static final int PORT = 8080;

    public static void main(String[] args) throws Exception {
   
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
   
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
   
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
   
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new NettyServerHandler());
                        }
                    });

            ChannelFuture f = b.bind(PORT).sync();
            f.channel().closeFuture().sync();
        } finally {
   
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
   
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   
        System.out.println("Received from client: " + msg);
        ctx.writeAndFlush(Unpooled.copiedBuffer("Echo: " + msg.toString(), Unpooled.copiedBuffer(msg.toString(), Unpooled.UTF_8)));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   
        cause.printStackTrace();
        ctx.close();
    }
}

客户端代码

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyClient {
   
    private static final int PORT = 8080;
    private static final String HOST = "localhost";

    public static void main(String[] args) throws Exception {
   
        EventLoopGroup group = new NioEventLoopGroup();

        try {
   
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
   
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
   
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new NettyClientHandler());
                        }
                    });

            ChannelFuture f = b.connect(HOST, PORT).sync();
            f.channel().closeFuture().sync();
        } finally {
   
            group.shutdownGracefully();
        }
    }
}

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class NettyClientHandler extends ChannelInboundHandlerAdapter {
   
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
   
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Server!", Unpooled.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   
        System.out.println("Received from server: " + msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   
        cause.printStackTrace();
        ctx.close();
    }
}

总结

通过上述技术综述,我们可以了解到 Java NIO 提供了一种非阻塞式的 I/O 模型,使得 Java 应用程序能够处理大量的并发连接。无论是使用原生的 Java NIO 还是基于 NIO 的框架如 Netty,都需要对 Buffer、Channel、Selector 等核心概念有一定的了解。无论是在日常开发还是面试准备中,熟悉这些知识都是非常重要的。

相关文章
|
5月前
|
机器学习/深度学习 PyTorch TensorFlow
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic,深度学习探索者。深耕TensorFlow与PyTorch,分享框架对比、性能优化与实战经验,助力技术进阶。
|
10月前
|
人工智能 监控 安全
NTP网络子钟的技术架构与行业应用解析
在数字化与智能化时代,时间同步精度至关重要。西安同步电子科技有限公司专注时间频率领域,以“同步天下”品牌提供可靠解决方案。其明星产品SYN6109型NTP网络子钟基于网络时间协议,实现高精度时间同步,广泛应用于考场、医院、智慧场景等领域。公司坚持技术创新,产品通过权威认证,未来将结合5G、物联网等技术推动行业进步,引领精准时间管理新时代。
|
10月前
|
人工智能 监控 Java
从NIO server到epoll源码解析
本文深入探讨了Java NIO与Linux epoll的结合使用,通过代码示例和源码分析,详细解析了NIO服务器的实现原理。首先介绍了NIO server demo,展示了如何利用Selector和Channel完成高并发网络框架的构建。接着通过源码探索,揭示了Selector、ServerSocketChannel等核心组件与epoll_create、epoll_ctl、epoll_wait三个核心方法的具体交互过程。最后总结了Java NIO的工作原理:通过Selector管理事件监听,将文件描述符注册到epoll_event中,利用epoll机制实现高效的IO多路复用。
175 0
|
6月前
|
机器学习/深度学习 人工智能 算法
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic带你深入卷积神经网络(CNN)核心技术,从生物启发到数学原理,详解ResNet、注意力机制与模型优化,探索视觉智能的演进之路。
608 11
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
472 0
|
6月前
|
安全 网络性能优化 网络虚拟化
网络交换机分类与功能解析
接入交换机(ASW)连接终端设备,提供高密度端口与基础安全策略;二层交换机(LSW)基于MAC地址转发数据,构成局域网基础;汇聚交换机(DSW)聚合流量并实施VLAN路由、QoS等高级策略;核心交换机(CSW)作为网络骨干,具备高性能、高可靠性的高速转发能力;中间交换机(ISW)可指汇聚层设备或刀片服务器内交换模块。典型流量路径为:终端→ASW→DSW/ISW→CSW,分层架构提升网络扩展性与管理效率。(238字)
1568 0
|
10月前
|
机器学习/深度学习 人工智能 算法
深度解析:基于卷积神经网络的宠物识别
宠物识别技术随着饲养规模扩大而兴起,传统手段存在局限性,基于卷积神经网络的宠物识别技术应运而生。快瞳AI通过优化MobileNet-SSD架构、多尺度特征融合及动态网络剪枝等技术,实现高效精准识别。其在智能家居、宠物医疗和防走失领域展现广泛应用前景,为宠物管理带来智能化解决方案,推动行业迈向新高度。
|
7月前
|
XML JSON JavaScript
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
177 0
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
|
9月前
|
开发者
鸿蒙仓颉语言开发教程:网络请求和数据解析
本文介绍了在仓颉开发语言中实现网络请求的方法,以购物应用的分类列表为例,详细讲解了从权限配置、发起请求到数据解析的全过程。通过示例代码,帮助开发者快速掌握如何在网络请求中处理数据并展示到页面上,减少开发中的摸索成本。
鸿蒙仓颉语言开发教程:网络请求和数据解析
|
10月前
|
网络架构
广播域与冲突域:解析网络技术中的复杂性。
总的来说,理解广播域和冲突域的概念可以使我们在设计或维护网络的过程中,更有效地管理通信流程,避免出现网络瓶颈,提成整体网络性能。就像是如何有效地运作一个市场,把每个人的需求和在合适的时间和地点配对,确保每个人的声音都被听到,每个人的需求都被满足。
343 11

推荐镜像

更多
  • DNS