Java NIO服务器端开发详解

下面详细讲解一下“Java NIO服务器端开发详解”的完整攻略。

简介

Java NIO(New IO,非阻塞IO)是Java中一套支持IO多路复用的新的API,相比于传统的IO,Java NIO能够更好地利用多核CPU的性能,同时也可以更好地实现高并发。

在Java NIO中,以Channel为中心,数据的读写以及网络的传输都是通过Channel进行的。Channel实现了IO多路复用技术,可以在一个线程中同时处理多个Channel的数据读写请求,因此可以实现更高的并发能力。

本文将介绍Java NIO服务器端开发的详细攻略,帮助读者掌握Java NIO编程。

Java NIO服务器端开发步骤

Java NIO服务器端开发的主要步骤包括以下几个:

  1. 创建ServerSocketChannel
  2. 设置为非阻塞模式
  3. 绑定端口
  4. 创建Selector
  5. 将ServerSocketChannel注册到Selector中
  6. 进入循环,不断监听客户端连接

下面对每个步骤进行详细说明。

创建ServerSocketChannel

要创建一个Java NIO服务器端程序,首先需要创建一个ServerSocketChannel对象。ServerSocketChannel是Java NIO中的一个通道(Channel)类型,可以监听TCP连接请求。

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

设置为非阻塞模式

默认情况下,ServerSocketChannel是阻塞模式。要使其变为非阻塞模式,需要调用configureBlocking(false)方法。

serverSocketChannel.configureBlocking(false);

绑定端口

调用ServerSocketChannel的bind()方法,绑定一个端口,用于监听客户端连接请求。

serverSocketChannel.bind(new InetSocketAddress(port));

创建Selector

Java NIO中的Selector可以监听多个Channel的IO事件,并选择已经准备好进行IO操作的Channel来处理,从而实现IO多路复用。在Java中,Selector是通过Selector.open()进行创建的。

Selector selector = Selector.open();

将ServerSocketChannel注册到Selector中

使用SelectionKey.OP_ACCEPT向Selector注册ServerSocketChannel,表示需要监听客户端连接请求。

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

进入循环,不断监听客户端连接

最后,要在一个无限循环中,等待客户端连接,从而实现长时间监听客户端请求。在循环中,需要轮询Selector上已经准备好了等待IO的Channel,进行相应的IO操作。

while (true) {
    // 阻塞等待
    int readyChannels = selector.select();

    // 遍历已经准备好进行IO操作的Channel
    Set<SelectionKey> selectedKeys = selector.selectedKeys();
    Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
    while (keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();

        // 处理连接请求
        if (key.isAcceptable()) {
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel client = server.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ);
        }

        // 处理读操作
        else if (key.isReadable()) {
            // TODO: 处理读操作
        }

        // 移除已经处理的事件
        keyIterator.remove();
    }
}

示例说明

示例1:Echo服务器

下面是一个简单的Echo服务器,用于接收客户端发送的字符串,然后原样返回给客户端。这个服务器使用Java NIO实现,支持高并发和非阻塞IO。

public class EchoServer {
    private static final int PORT = 8000;

    public void start() throws Exception {
        // 创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 设置为非阻塞模式
        serverSocketChannel.configureBlocking(false);

        // 绑定端口
        serverSocketChannel.bind(new InetSocketAddress(PORT));

        // 创建Selector
        Selector selector = Selector.open();

        // 将ServerSocketChannel注册到Selector中
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 进入循环,不断监听客户端连接
        while (true) {
            // 阻塞等待
            int readyChannels = selector.select();

            // 遍历已经准备好进行IO操作的Channel
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                // 处理连接请求
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                }

                // 处理读操作
                else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytes = client.read(buffer);
                    if (bytes > 0) {
                        buffer.flip();
                        client.write(buffer);
                    }
                }

                // 移除已经处理的事件
                keyIterator.remove();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        EchoServer server = new EchoServer();
        server.start();
    }
}

示例2:文件服务器

下面是一个文件服务器示例,用于接收客户端发送的文件路径,然后返回该文件的内容。

public class FileServer {
    private static final int PORT = 8000;

    public void start() throws Exception {
        // 创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 设置为非阻塞模式
        serverSocketChannel.configureBlocking(false);

        // 绑定端口
        serverSocketChannel.bind(new InetSocketAddress(PORT));

        // 创建Selector
        Selector selector = Selector.open();

        // 将ServerSocketChannel注册到Selector中
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 进入循环,不断监听客户端连接
        while (true) {
            // 阻塞等待
            int readyChannels = selector.select();

            // 遍历已经准备好进行IO操作的Channel
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                // 处理连接请求
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                }

                // 处理读操作
                else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytes = client.read(buffer);

                    if (bytes > 0) {
                        buffer.flip();
                        String filename = Charset.forName("UTF-8").decode(buffer).toString();

                        // 读取文件内容
                        File file = new File(filename);
                        FileInputStream fis = new FileInputStream(file);
                        FileChannel fileChannel = fis.getChannel();
                        ByteBuffer fileBuffer = ByteBuffer.allocate((int) fileChannel.size());
                        fileChannel.read(fileBuffer);
                        fileBuffer.flip();
                        client.write(fileBuffer);

                        fileChannel.close();
                        fis.close();
                    }
                }

                // 移除已经处理的事件
                keyIterator.remove();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        FileServer server = new FileServer();
        server.start();
    }
}

以上就是Java NIO服务器端开发的详细攻略,希望对您有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java NIO服务器端开发详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 详解java中继承关系类加载顺序问题

    详解Java中继承关系类加载顺序问题 介绍 当一个Java类继承另一个Java类时,这两个类的加载顺序会有所不同。这篇攻略将帮助你完全了解这个问题,以及解决相关的问题。 加载顺序 当一个Java程序启动时,JVM会按以下顺序加载类: 加载超类 解析超类中的静态字段和静态块 加载子类 解析子类中的静态字段和静态块 执行超类构造函数 执行子类构造函数 示例 示例…

    other 2023年6月27日
    00
  • TabLayout用法详解及自定义样式

    项目中常见的 TabLayout 控件是 Android Design Support Library 中的 TabLayout,它可以让我们轻松地实现标签页切换,特别适合用于一些包含多个页面的 App 中。本文将介绍 TabLayout 的用法及自定义样式的实现。 TabLayout 简介 TabLayout 是一个可滚动标签页的控件,和 ViewPage…

    other 2023年6月25日
    00
  • Win11加密功能怎么添加到右键菜单? Win11加密解密右键快捷添加方法

    以下是“Win11加密功能怎么添加到右键菜单? Win11加密解密右键快捷添加方法”的完整攻略: 添加Win11加密解密右键菜单 首先打开“注册表编辑器”,可以在Win11系统中按下Win + R快捷键打开“运行”窗口,输入regedit命令并回车即可。 导航到HKEY_CLASSES_ROOT\*\shell节点。 右键单击“shell”节点,并选择“新建…

    other 2023年6月27日
    00
  • Android实现RecyclerView嵌套流式布局的详细过程

    Android实现RecyclerView嵌套流式布局的详细过程 在Android中,要实现RecyclerView嵌套流式布局,可以使用以下步骤: 步骤一:添加依赖 首先,在项目的build.gradle文件中添加以下依赖: implementation ‘com.google.android.material:material:1.4.0’ implem…

    other 2023年7月28日
    00
  • python生成IP段的方法

    Python生成IP段的方法攻略 生成IP段是指根据给定的起始IP地址和结束IP地址,生成一个包含这两个IP地址之间所有IP地址的列表。在Python中,可以使用一些库和方法来实现这个功能。下面是一个详细的攻略,包含了两个示例说明。 步骤1:导入必要的库 首先,我们需要导入ipaddress库,它提供了处理IP地址的功能。 import ipaddress …

    other 2023年7月31日
    00
  • idea一招搞定同步所有配置(导入或导出所有配置)

    下面我将详细讲解 “idea一招搞定同步所有配置(导入或导出所有配置)” 的完整攻略。 一、背景介绍 首先,需要知道的是,IntelliJ IDEA 是一款功能丰富、使用方便的 Java 集成开发环境,也是开发者必不可少的工具之一。在使用 IntelliJ IDEA 的过程中,我们往往需要配置各种插件、主题、快捷键等等,这些配置信息非常重要,我们希望能够在不…

    other 2023年6月25日
    00
  • 页面加载完成后再执行JS的jquery写法以及区别说明

    在网页中,我们经常需要在页面加载完成后再执行一些 JavaScript 代码。这个需求非常普遍,比如我们需要在 DOM 树构建完成后再去操作元素,或者需要等待图片等资源加载完成后再进行后续的逻辑处理。在这种需求下,我们可以使用 JQuery 提供的 ready() 方法来处理,同时,使用 ready() 方法还有一定的性能优势。下面是详细的攻略: 什么是 j…

    other 2023年6月25日
    00
  • Oracle密码过期如何取消密码180天限制及密码180天过期,账号锁住的问题

    下面是针对Oracle密码过期的取消、账号锁定等常见问题的完整攻略: Oracle密码过期取消及密码过期问题处理 密码过期取消 有时候在登录Oracle数据库时会提示密码过期,此时用户需要修改密码才能登录,否则会因为账号被锁定而无法登录。出于安全考虑,Oracle默认情况下设定了密码的有效期限制,时间为180天。然而,对于一些临时安装或测试数据库,这个限制可…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部