Java NIO 开发

news2024/11/17 2:35:22

Java NIO 新篇介绍加示例代码

在这里插入图片描述

Java NIO(New IO)是 JDK 1.4 引入的一组新的 I/O API,用于支持非阻塞式 I/O 操作。相比传统的 Java
IO API,NIO 提供了更快、更灵活的 I/O 操作方式,可以用于构建高性能网络应用程序。

Java NIO 的主要组成部分包括:

Channel:通道是一个在应用程序和文件、网络套接字之间的连接。可以通过通道来进行数据的读取和写入。
Buffer:缓冲区是一个容器,用于存储数据。在 NIO 中,所有的数据读取和写入都是通过缓冲区进行的。
Selector:选择器用于监听多个 NIO 通道的事件,如读写事件。当某个通道发生事件时,选择器会通知该事件并对其进行处理。 相比传统的
Java IO,Java NIO 的优点包括:

非阻塞模式:NIO 可以使用非阻塞模式进行网络编程,使程序不必等待网络操作完成才能进行其他操作,提高了程序的响应速度。
多路复用:一个线程可以同时处理多个 NIO 通道,减少了线程的开销和资源占用。 缓冲区操作:NIO
使用缓冲区进行数据读取和写入,可以提高数据访问速度。 下面是 Java NIO 常用类和接口:

Channel:提供了各种类型的通道接口,如 FileChannel、DatagramChannel、SocketChannel 和
ServerSocketChannel 等。 Buffer:提供了各种类型的缓冲区实现,如
ByteBuffer、CharBuffer、ShortBuffer 和 DoubleBuffer 等。 Selector:提供了
Selector 接口,用于监听多个通道的事件,可以使用一个线程处理多个通道。 总之,Java NIO
提高了网络编程的效率和性能,使得程序可以处理更多并发请求。但同时需要注意 NIO 的复杂性和学习难度,需要仔细理解其原理和使用规范。

我在早期有讲过Java NIO的基本用法 如果初学者可以 浏览 早期的Java NIO 文章

一,Channel实现类

Channel实现类 讲解

在Java NIO中,Channel是一个重要的概念,它代表着一个可以进行读写操作的实体,可以与文件、网络套接字等进行交互。

Java NIO提供了多种不同类型的Channel实现类,下面是其中一些常用的实现类:

  1. FileChannel:用于读写文件数据的通道,可以从文件中读取数据到缓冲区,也可以将缓冲区中的数据写入文件。
    FileChannel类是Java NIO中用于对文件进行读写操作的通道。它提供了一系列方法来实现文件的读取和写入操作。以下是FileChannel类中常用的方法:
  1. open(Path path, OpenOption... options):静态方法,用于打开一个文件通道。参数path表示文件路径,options表示打开文件的选项,例如StandardOpenOption.READ表示以只读方式打开文件,StandardOpenOption.WRITE表示以写入方式打开文件等。

  2. read(ByteBuffer dst):从通道中读取数据到指定的缓冲区。返回值为读取的字节数,如果返回-1表示已经读取到文件末尾。

  3. write(ByteBuffer src):将指定的缓冲区中的数据写入到通道中。返回值为写入的字节数。

  4. position()position(long newPosition):获取或设置当前通道的位置。position()方法返回当前位置,position(long newPosition)方法将位置设置为指定的值。

  5. size():获取通道关联文件的大小。

  6. truncate(long size):将通道关联文件截断为指定的大小。

  7. force(boolean metaData):强制将通道关联文件的内容刷新到磁盘上。

  8. transferTo(long position, long count, WritableByteChannel target)transferFrom(ReadableByteChannel src, long position, long count):这两个方法用于在通道之间直接传输数据,可以避免数据的中间复制。

  9. lock()tryLock():用于对通道进行加锁操作,实现文件的独占访问。

  10. close():关闭通道。

以上是FileChannel类中的一些常用方法,通过这些方法可以实现对文件的读写操作。需要注意的是,在使用FileChannel进行读写操作时,通常需要结合ByteBuffer类来完成数据的读取和写入。

  1. SocketChannel:用于进行TCP连接的通道,可以通过SocketChannel与远程服务器建立连接,并进行数据的读写操作。
    SocketChannel是Java NIO中用于进行TCP连接的通道,它提供了一系列方法来实现网络数据的读取和写入操作。以下是SocketChannel类中常用的方法:
  1. open():静态方法,用于打开一个SocketChannel。

  2. connect(SocketAddress remote):连接到指定的远程服务器。参数remote表示远程服务器的地址。

  3. finishConnect():完成连接操作。在调用connect()方法后,需要调用finishConnect()方法等待连接完成。

  4. read(ByteBuffer dst):从通道中读取数据到指定的缓冲区。返回值为读取的字节数,如果返回-1表示已经读取到流的末尾。

  5. write(ByteBuffer src):将指定的缓冲区中的数据写入到通道中。返回值为写入的字节数。

  6. isOpen():判断通道是否处于打开状态。

  7. isConnected():判断是否已经连接到远程服务器。

  8. socket():获取与此通道关联的套接字。

  9. getRemoteAddress()getLocalAddress():分别获取远程和本地的地址。

  10. setOption(SocketOption<T> name, T value)getOption(SocketOption<T> name):用于设置和获取套接字选项。

  11. configureBlocking(boolean block):设置通道的阻塞模式。如果block为true,表示通道为阻塞模式,否则为非阻塞模式。

  12. register(Selector sel, int ops):将通道注册到指定的选择器中,以便进行选择操作。

  13. close():关闭通道。

以上是SocketChannel类中的一些常用方法,通过这些方法可以实现网络数据的读取和写入操作。需要注意的是,在使用SocketChannel进行读写操作时,通常需要结合ByteBuffer类来完成数据的读取和写入。

  1. ServerSocketChannel:用于监听TCP连接请求的通道,可以通过ServerSocketChannel监听特定的端口,并等待客户端的连接请求。

ServerSocketChannel是Java
NIO中用于创建服务器端的通道,它提供了一系列方法来实现服务器的监听和接收客户端连接。以下是ServerSocketChannel类中常用的方法:

  1. open():静态方法,用于打开一个ServerSocketChannel。

  2. bind(SocketAddress local):绑定服务器的本地地址。参数local表示本地地址。

  3. accept():接受客户端的连接请求,并返回一个SocketChannel用于与客户端进行通信。

  4. configureBlocking(boolean block):设置通道的阻塞模式。如果block为true,表示通道为阻塞模式,否则为非阻塞模式。

  5. isOpen():判断通道是否处于打开状态。

  6. socket():获取与此通道关联的服务器套接字。

  7. getLocalAddress():获取服务器绑定的本地地址。

  8. setOption(SocketOption<T> name, T value)getOption(SocketOption<T> name):用于设置和获取套接字选项。

  9. register(Selector sel, int ops):将通道注册到指定的选择器中,以便进行选择操作。

  10. close():关闭通道。

以上是ServerSocketChannel类中的一些常用方法,通过这些方法可以实现服务器的监听和接受客户端连接。需要注意的是,在使用ServerSocketChannel时,通常需要结合SocketChannel来与客户端进行通信。

  1. DatagramChannel:用于进行UDP连接的通道,可以通过DatagramChannel发送和接收UDP数据包。
    DatagramChannel是Java NIO中用于进行UDP通信的通道,它提供了一系列方法来实现数据的发送和接收。以下是DatagramChannel类中常用的方法:
  1. open():静态方法,用于打开一个DatagramChannel。

  2. bind(SocketAddress local):将通道绑定到指定的本地地址。参数local表示本地地址。

  3. receive(ByteBuffer dst):从通道中接收数据,并将数据存储到指定的缓冲区中。返回值为接收的字节数,如果返回-1表示没有数据可读。

  4. send(ByteBuffer src, SocketAddress target):将指定的缓冲区中的数据发送到目标地址。参数src表示要发送的数据,target表示目标地址。

  5. configureBlocking(boolean block):设置通道的阻塞模式。如果block为true,表示通道为阻塞模式,否则为非阻塞模式。

  6. isOpen():判断通道是否处于打开状态。

  7. socket():获取与此通道关联的套接字。

  8. getLocalAddress():获取通道绑定的本地地址。

  9. setOption(SocketOption<T> name, T value)getOption(SocketOption<T> name):用于设置和获取套接字选项。

  10. close():关闭通道。

以上是DatagramChannel类中的一些常用方法,通过这些方法可以实现UDP数据的发送和接收。需要注意的是,在使用DatagramChannel进行数据发送和接收时,通常需要结合ByteBuffer类来完成数据的读取和写入。

  1. Pipe.SinkChannel和Pipe.SourceChannel:用于在同一进程内进行线程之间的通信,可以通过Pipe.SinkChannel向管道中写入数据,然后通过Pipe.SourceChannel从管道中读取数据。
    Pipe是Java NIO中用于在两个线程之间进行通信的管道,其中包含了SinkChannel和SourceChannel两个通道。下面是Pipe.SinkChannel和Pipe.SourceChannel常用的方法:

Pipe.SinkChannel常用方法:

  1. write(ByteBuffer src):将指定的字节缓冲区中的数据写入到通道中。

  2. close():关闭通道。

  3. isOpen():判断通道是否处于打开状态。

  4. configureBlocking(boolean block):设置通道的阻塞模式。如果block为true,表示通道为阻塞模式,否则为非阻塞模式。

  5. validOps():返回此通道支持的操作集合。

Pipe.SourceChannel常用方法:

  1. read(ByteBuffer dst):从通道中读取数据,并将数据存储到指定的字节缓冲区中。

  2. close():关闭通道。

  3. isOpen():判断通道是否处于打开状态。

  4. configureBlocking(boolean block):设置通道的阻塞模式。如果block为true,表示通道为阻塞模式,否则为非阻塞模式。

  5. validOps():返回此通道支持的操作集合。

需要注意的是,Pipe是一个单向的通道,通过Pipe.SinkChannel向Pipe.SourceChannel传输数据。在使用Pipe进行通信时,一般会创建一个Pipe实例,并通过sink()source()方法获取对应的SinkChannel和SourceChannel对象,然后在不同的线程中使用这两个通道进行数据的读写操作。

Channel实现类 示例代码

这些Channel实现类都是抽象类,具体的实例化需要通过工厂方法来创建。在使用Channel进行数据读写时,需要结合Buffer类来完成数据的读写操作。
下面是一些Java示例代码,展示了FileChannel、SocketChannel、ServerSocketChannel、DatagramChannel、Pipe.SinkChannel和Pipe.SourceChannel的基本用法:

  1. FileChannel 示例代码:
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileChannelExample {
    public static void main(String[] args) throws Exception {
        RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
        FileChannel channel = file.getChannel();

        String data = "Hello, World!";
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(data.getBytes());
        buffer.flip();

        channel.write(buffer);

        channel.close();
        file.close();
    }
}
  1. SocketChannel 示例代码:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class SocketChannelExample {
    public static void main(String[] args) throws Exception {
        SocketChannel channel = SocketChannel.open();
        channel.connect(new InetSocketAddress("localhost", 8080));

        String data = "Hello, Server!";
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(data.getBytes());
        buffer.flip();

        channel.write(buffer);

        buffer.clear();
        channel.read(buffer);
        buffer.flip();

        String response = new String(buffer.array(), 0, buffer.limit());
        System.out.println("Server response: " + response);

        channel.close();
    }
}
  1. ServerSocketChannel 示例代码:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class ServerSocketChannelExample {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.socket().bind(new InetSocketAddress(8080));

        SocketChannel channel = serverChannel.accept();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer);
        buffer.flip();

        String request = new String(buffer.array(), 0, buffer.limit());
        System.out.println("Received request: " + request);

        String response = "Hello, Client!";
        buffer.clear();
        buffer.put(response.getBytes());
        buffer.flip();

        channel.write(buffer);

        channel.close();
        serverChannel.close();
    }
}
  1. DatagramChannel 示例代码:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class DatagramChannelExample {
    public static void main(String[] args) throws Exception {
        DatagramChannel channel = DatagramChannel.open();
        channel.bind(new InetSocketAddress(8080));

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.receive(buffer);
        buffer.flip();

        String request = new String(buffer.array(), 0, buffer.limit());
        System.out.println("Received request: " + request);

        String response = "Hello, Client!";
        buffer.clear();
        buffer.put(response.getBytes());
        buffer.flip();

        channel.send(buffer, new InetSocketAddress("localhost", 8888));

        channel.close();
    }
}
  1. Pipe.SinkChannel 和 Pipe.SourceChannel 示例代码:
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;

public class PipeChannelExample {
    public static void main(String[] args) throws Exception {
        Pipe pipe = Pipe.open();
        Pipe.SinkChannel sinkChannel = pipe.sink();
        Pipe.SourceChannel sourceChannel = pipe.source();

        String data = "Hello, Pipe!";
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(data.getBytes());
        buffer.flip();

        sinkChannel.write(buffer);

        buffer.clear();
        sourceChannel.read(buffer);
        buffer.flip();

        String response = new String(buffer.array(), 0, buffer.limit());
        System.out.println("Received response: " + response);

        sinkChannel.close();
        sourceChannel.close();
    }
}

这些示例代码展示了不同类型的通道的基本用法,可以根据需要进行修改和扩展。请注意,这些示例仅用于演示目的,实际使用时需要进行适当的错误处理和资源释放。

二 ,Buffer实现类

1.Buffer实现类 讲解

在Java NIO中,有以下几个常用的Buffer实现类:

  1. ByteBuffer:最常用的Buffer实现类,用于读写字节数据。可以通过ByteBuffer.allocate(int capacity)方法创建一个ByteBuffer实例。

  2. CharBuffer:用于读写字符数据,底层实际上是基于ByteBuffer实现的。可以通过CharBuffer.allocate(int capacity)方法创建一个CharBuffer实例。

  3. ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer:分别用于读写短整型、整型、长整型、浮点型和双精度浮点型数据。它们都是通过ByteBuffer进行实现的,可以通过相应的allocate方法创建对应类型的Buffer实例。

这些Buffer实现类都提供了一系列的方法来读写数据、管理指针位置等操作。例如,常用的方法包括:

  • put():向Buffer中写入数据。
  • get():从Buffer中读取数据。
  • flip():将Buffer从写模式切换到读模式,重置position和limit。
  • clear():清空Buffer,重置position、limit和mark。
  • rewind():将position重置为0,保持limit不变,可重新读取之前读过的数据。
  • compact():将未读完的数据移到Buffer的开头,position设置为已读数据的末尾,limit设置为capacity。

这些Buffer实现类提供了灵活的读写操作,可以根据需要选择合适的Buffer类型,并结合通道(Channel)进行数据的读写和传输。

2.Buffer实现类 示例代码

下面是ByteBuffer、CharBuffer和ShortBuffer的示例代码,分别演示了它们的基本用法:

  1. ByteBuffer 示例代码:
import java.nio.ByteBuffer;

public class ByteBufferExample {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        buffer.put((byte) 1);
        buffer.put((byte) 2);
        buffer.put((byte) 3);

        buffer.flip();

        while (buffer.hasRemaining()) {
            byte value = buffer.get();
            System.out.println(value);
        }
    }
}
  1. CharBuffer 示例代码:
import java.nio.CharBuffer;

public class CharBufferExample {
    public static void main(String[] args) {
        CharBuffer buffer = CharBuffer.allocate(10);

        buffer.put('A');
        buffer.put('B');
        buffer.put('C');

        buffer.flip();

        while (buffer.hasRemaining()) {
            char value = buffer.get();
            System.out.println(value);
        }
    }
}
  1. ShortBuffer 示例代码:
import java.nio.ShortBuffer;

public class ShortBufferExample {
    public static void main(String[] args) {
        ShortBuffer buffer = ShortBuffer.allocate(10);

        buffer.put((short) 1);
        buffer.put((short) 2);
        buffer.put((short) 3);

        buffer.flip();

        while (buffer.hasRemaining()) {
            short value = buffer.get();
            System.out.println(value);
        }
    }
}

这些示例代码演示了ByteBuffer、CharBuffer和ShortBuffer的基本用法。创建Buffer实例后,可以使用put()方法向缓冲区中写入数据,使用flip()方法将缓冲区从写模式切换到读模式,然后使用get()方法读取数据。hasRemaining()方法用于判断是否还有剩余的数据可读取。

请注意,示例中的容量(capacity)和实际写入的数据量是一致的,这是为了简化代码。在实际应用中,通常会根据需要调整缓冲区的容量,并进行适当的容量检查和数据处理。

在Java NIO中,Selector是一个多路复用器(Multiplexer)的实现类,用于监控多个通道的状态,以实现单线程处理多个通道的I/O操作。

三,Selector 实现类

1.Selector 实现类

Selector类是Java NIO中用于多路复用非阻塞I/O的关键组件。下面是Selector类常用的方法:

  1. open():静态方法,用于创建一个新的Selector实例。
Selector selector = Selector.open();
  1. close():关闭选择器。
selector.close();
  1. select():阻塞等待就绪的通道,返回已就绪通道的数量。
int numReadyChannels = selector.select();
  1. select(long timeout):阻塞等待就绪的通道,最多等待指定的超时时间(毫秒),返回已就绪通道的数量。
int numReadyChannels = selector.select(5000);
  1. selectNow():非阻塞地检查是否有就绪的通道,立即返回已就绪通道的数量。
int numReadyChannels = selector.selectNow();
  1. wakeup():唤醒阻塞在select()select(long timeout)方法上的线程。
selector.wakeup();
  1. keys():返回当前注册到选择器上的所有选择键(SelectionKey)的集合。
Set<SelectionKey> keys = selector.keys();
  1. selectedKeys():返回当前就绪的选择键(SelectionKey)的集合。
Set<SelectionKey> selectedKeys = selector.selectedKeys();
  1. register(SelectableChannel channel, int interestOps):将通道注册到选择器上,并指定感兴趣的事件。
channel.register(selector, SelectionKey.OP_READ);
  1. validOps():返回选择器支持的操作集合。
int validOps = selector.validOps();
  1. cancel():取消选择键的注册。
selectionKey.cancel();
  1. keys():返回当前注册到选择器上的所有选择键(SelectionKey)的集合。
Set<SelectionKey> keys = selector.keys();
  1. selectedKeys():返回当前就绪的选择键(SelectionKey)的集合。
Set<SelectionKey> selectedKeys = selector.selectedKeys();

这些方法提供了对选择器的基本操作,包括创建、关闭、等待就绪通道、注册通道、取消注册等。通过这些方法,可以实现多路复用非阻塞I/O的功能,高效地处理多个通道的I/O事件。在实际应用中,根据具体需求选择合适的方法来管理和操作选择器。

Java NIO中提供了一个名为Selector的抽象类,它的具体实现类是java.nio.channels.Selector。通过Selector.open()方法可以创建一个Selector实例。

2.Selector 实现类 示例代码

以下是一个简单的示例代码,演示了Selector的基本用法:

import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;

public class SelectorExample {
    public static void main(String[] args) {
        try {
            // 创建一个 Selector
            Selector selector = Selector.open();

            // 创建一个 ServerSocketChannel,并注册到 Selector 上
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false); // 设置为非阻塞模式
            serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册监听 ACCEPT 事件

            // 循环等待事件发生
            while (true) {
                // 阻塞等待事件发生
                int numReadyChannels = selector.select();

                // 处理已就绪的事件
                if (numReadyChannels > 0) {
                    Set<SelectionKey> selectedKeys = selector.selectedKeys();
                    Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

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

                        if (key.isAcceptable()) {
                            // 处理 ACCEPT 事件
                        } else if (key.isReadable()) {
                            // 处理 READ 事件
                        } else if (key.isWritable()) {
                            // 处理 WRITE 事件
                        }

                        keyIterator.remove(); // 移除已处理的事件
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在示例代码中,首先通过Selector.open()方法创建一个Selector实例。然后创建一个ServerSocketChannel,并将其注册到Selector上,指定监听OP_ACCEPT事件。接下来,进入一个无限循环,调用select()方法阻塞等待事件发生。当有事件就绪时,调用selectedKeys()方法获取已就绪的事件集合,然后遍历处理每个事件。

在实际应用中,可以根据需要注册不同类型的事件,如OP_READOP_WRITE等,并在处理事件时执行相应的操作。同时,还可以使用Selector的其他方法,如wakeup()selectNow()等,来控制选择器的行为。

需要注意的是,Selector是线程安全的,可以在多个线程中共享一个选择器。但是,对于同一个选择器,不应该在多个线程中同时调用select()方法或修改注册的通道和事件。通常建议将选择器的操作放在单独的线程中执行,以避免竞争条件和线程安全问题。

三,Java NIO中常用的Channel、Buffer和Selector的使用代码模板示例代码

以下是Java NIO中常用的Channel、Buffer和Selector的使用代码模板示例代码:

Channel示例代码:

// 创建一个SocketChannel并连接到指定地址
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));

// 判断是否连接成功
while (!socketChannel.finishConnect()) {
    // 连接未完成,继续等待
}

// 发送数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello, Server!".getBytes());
buffer.flip();
socketChannel.write(buffer);

// 接收数据
buffer.clear();
socketChannel.read(buffer);
buffer.flip();
System.out.println(new String(buffer.array()));

// 关闭通道
socketChannel.close();

Buffer示例代码:

// 创建一个ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(1024);

// 写入数据
buffer.put("Hello, World!".getBytes());

// 读取数据
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
System.out.println(new String(bytes));

// 清空缓冲区
buffer.clear();

Selector示例代码:

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

// 创建一个ServerSocketChannel并绑定到指定端口
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);

// 将ServerSocketChannel注册到Selector上,并监听连接事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

// 等待事件发生
while (selector.select() > 0) {
    // 获取所有已经就绪的事件
    Set<SelectionKey> selectionKeys = selector.selectedKeys();
    Iterator<SelectionKey> iterator = selectionKeys.iterator();

    // 处理所有已经就绪的事件
    while (iterator.hasNext()) {
        SelectionKey selectionKey = iterator.next();
        if (selectionKey.isAcceptable()) {
            // 处理连接事件
            ServerSocketChannel serverChannel = (ServerSocketChannel) selectionKey.channel();
            SocketChannel socketChannel = serverChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
            // 处理读取事件
            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int len = 0;
            while ((len = socketChannel.read(buffer)) > 0) {
                buffer.flip();
                System.out.println(new String(buffer.array(), 0, len));
                buffer.clear();
            }
            if (len == -1) {
                // 客户端关闭连接
                socketChannel.close();
            }
        }
        // 移除已经处理过的事件
        iterator.remove();
    }
}

// 关闭Selector和ServerSocketChannel
selector.close();
serverSocketChannel.close();

以上是Java NIO中常用的Channel、Buffer和Selector的使用代码模板示例代码。需要注意的是,这些代码仅供参考,实际使用时需要根据具体情况进行调整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1142659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电机控制方案汇总

以IR2104/IR2184为例&#xff08;第1讲&#xff09; NXP智能车永磁直流有刷电动机驱动器 (1)BTN7971B BTN7970 BTN7960 半桥 两片芯片即可驱动一个电机。好用 有个队有KEA128例程 (2)HIP4082 全桥 一片芯片4个MOS驱动一个电机。 好用 (3)IR2184 半桥 两片芯片4个MOS驱动一个电机…

Linux系统启动异常完整修复过程

当Linux启动时出现报错提示“Give root password for maintenance”&#xff0c;表明系统检测到某些系统文件可能损坏或丢失&#xff0c;因此需要进入维护模式来修复。此时&#xff0c;需要输入root用户的密码才能进入维护模式&#xff0c;以修复损坏的文件。 Linux系统无法正常…

MyBaties存储和查询json格式的数据(实体存储查询版本)

最近在做的功能&#xff0c;由于别的数据库有值&#xff0c;需要这边的不同入口的进来查询&#xff0c;所以需要同步过来&#xff0c;如果再继续一个一个生成列对应处理感觉不方便&#xff0c;如果没有别的操作&#xff0c;只是存储和查询&#xff0c;那就可以用MySql支持的jso…

数字孪生技术:智慧港口的未来

随着全球贸易的不断增长&#xff0c;港口运营已经成为国际贸易的重要枢纽。港口管理者和运营商正面临着巨大的挑战&#xff0c;需要应对日益复杂的物流网络、安全威胁、环境可持续性和客户需求。在这个背景下&#xff0c;数字孪生技术已经崭露头角&#xff0c;为智慧港口的建设…

安装sharepoint订阅版过程

一、安装需求 1、计算资源需求 CPU 4核&#xff0c;内存24G以上&#xff0c;硬盘300G 2、操作系统 Windows Server 2019 标准或数据中心 Windows Server 2022 标准或数据中心 3、数据库 支持数据库兼容性级别 150 的SQL Server 2019 或更高版本SQL Server 2022&#xf…

windows qemu安装飞腾Aarch64 操作系统 亲测

在win7&#xff08;X86架构CPU&#xff09;下使用QEMU虚拟机运行银河麒麟操作系统&#xff08;ARM架构CPU&#xff09; 1、下载并安装QEMU虚拟机软件 https://qemu.weilnetz.de/w64/2020/ 2、准备好ARM银河麒麟操作系统.iso文件 这里是 Kylin-Desktop-V10-Release-2107-ar…

MySQL主从同步-Gtid

【百炼成魔】MySQL主从同步-Gtid 服务器准备 IP节点配置系统版本191.168.117.143master2c2g40gcentos 7.9192.168.117.142slave2c2g40gcentos 7.9 环境准备 下面操作需要在两台机器都操作 关闭防火墙 systemctl stop firewalld && systemctl disable firewalldse…

如何写考勤分析报告?

如何写考勤分析报告&#xff1f;首先你得知道考勤分析报告需要分析哪些数据。 一般来说&#xff0c;一份完整的考勤分析报告&#xff0c;必须要分析的数据有8大类—— 基本考勤数据出勤数据加班数据迟到早退数据请假数据休息日和节假日数据打卡数据异常情况数据 除此之外还需…

lesson-2C++类与对象(中)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 类的6个默认成员函数 构造函数 概念 特性 析构函数 概念 特性 拷贝构造函数 概念 特性 赋值运算符重载 运算符重载 赋值运算符重载 前置和后置重载 日期类的实现 类的6个默认成员函数 如果一个类中什么…

基于java jsp垃圾分类管理系统的设计与实现

摘 要 我们的时代像一辆高速飞驰的列车&#xff0c;带着互联网冲入了我们的视野内&#xff0c;并且大家对生活品质的追求也更加地高了。花变成了人们生活中的一个常见品。鲜花的需求量在这些年来逐步增长&#xff0c;花本身就具有“高颜值”&#xff0c;还伴有特殊的香味&a…

内核进程的调度与进程切换

进程被创建到了链表中&#xff0c;如何再进行进一步的调用和调用&#xff1f; 进程调度 void schedule(void)&#xff1b; 进程调度 switch_to(next); 进程切换函数 void schedule(void) {int i,next,c;struct task_struct ** p;/* check alarm, wake up any i…

秒级启动的集成测试框架

本文介绍了一种秒级启动的集成测试框架&#xff0c;使用该框架可以方便的修改和完善测试用例&#xff0c;使得测试用例成为测试过程的产物。 背景 传统的单元测试&#xff0c;测试的范围往往非常有限&#xff0c;常常覆盖的是一些工具类、静态方法或者较为底层纯粹的类实现&…

群晖上搭建teamspeak3语音服务器

什么是 TeamSpeak &#xff1f; TeamSpeak &#xff08;简称 TS&#xff09;是一款团队语音通讯工具&#xff0c;但比一般的通讯工具具有更多的功能而且使用方便。它由服务器端程序和客户端程序两部分组成&#xff0c;如果不是想自己架设 TS 服务器&#xff0c;只需下载客户端程…

OpenCV学习(四)——轨迹栏(调色板与不同通道图像)

轨迹栏 4. OpenCV轨迹栏4.1 轨迹栏作为调色板4.2 轨迹栏显示不同通道图像 4. OpenCV轨迹栏 会用到以下主要两个函数 cv2.createTrackbar(trackbarName, windowName, value, count, onChange)创建轨迹栏 主要参数&#xff1a; trackbarName&#xff1a;轨迹栏名称windowName…

视频分辨率/帧率/码率选择参考

1. 视频码率与分辨率的参考表 1080&#xff0a;720的分辨率&#xff0c;用5000K左右&#xff1b; 720&#xff0a;576的分辨率&#xff0c;用3500K左右&#xff1b; 640&#xff0a;480的分辨率&#xff0c;用1500K左右。 2. 计算公式 基本算法&#xff1a;码率&#xff08;kb…

基于Canal同步MySQL数据到Elasticsearch

基于Canal同步MySQL数据到Elasticsearch 基于 canal 同步 mysql 的数据到 elasticsearch 中。 1、canal-server 相关软件的安装请参考&#xff1a;《Canal实现数据同步》 1.1 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmln…

中国地名信息库

地名是社会基本公共信息&#xff0c;是历史文化的重要载体。 2014年至2018年&#xff0c;国家启动实施并完成了第二次全国地名普查工作&#xff0c;全国共计采集地名1320多万条&#xff0c;修测标绘地名图2.4万多幅&#xff0c;新设更新地名标志68万多块&#xff0c;普遍建立了…

server2012 通过防火墙开启局域网内限定IP进行远程桌面连接

我这里需要被远程桌面的电脑系统版本为windows server2012 1、打开允许远程连接设置 2、开启防火墙 3、设置允许“远程桌面应用”通过防火墙 勾选”远程桌面“ 3、入站规则设置 高级设置→入站规则→远程桌面-用户模式(TCP-In) 进入远程桌面属性的作用域——>远程IP地址—…

演讲比赛常见误区及解决方法

演讲比赛常见误区及解决方法 一、演讲内容选择错误 1. 主题选择不合理 许多参赛者选择的主题内容&#xff0c;与比赛题目要求或听众背景不符&#xff0c;难以引起听众的兴趣。正确选择主题应考虑以下几点&#xff1a; - 主题应与比赛题目要求相符合&#xff0c;切合比赛定位…

《C和指针》(5)操作符和表达式

问题 下面这个表达式的类型和值分别是什么? 答&#xff1a;该值为2.0&#xff0c;如果要进行浮点除法&#xff0c;请使用以下表达式 下面这个程序的结果是什么&#xff1f; 答&#xff1a;这是一个狡猾的问题。比较明显的回答是-10(2-3 *4),但实际上它因编译器而异。乘法运…