Java 如何将MappedByteBuffer写入套接字输出流(服务器到客户端),而不复制

Java 如何将MappedByteBuffer写入套接字输出流(服务器到客户端),而不复制,java,nio,java-io,virtual-memory,memory-mapped-files,Java,Nio,Java Io,Virtual Memory,Memory Mapped Files,在Java代码中,我使用MappedByteBuffer映射了一个文件区域,我需要将其发送到客户端(写入Outputstream)。我需要确保在向套接字发送/写入时,由于内存限制,它不会创建任何副本。我怎样才能做到这一点?Bytebuffer.array()是否可以用于此目的 共享代码。注意:FileChannel是只读的,我需要按原样发送ByteBuffer数据 private void writeData(Socket clientSocket, MappedByteBuffer byteB

在Java代码中,我使用MappedByteBuffer映射了一个文件区域,我需要将其发送到客户端(写入Outputstream)。我需要确保在向套接字发送/写入时,由于内存限制,它不会创建任何副本。我怎样才能做到这一点?Bytebuffer.array()是否可以用于此目的

共享代码。注意:FileChannel是只读的,我需要按原样发送ByteBuffer数据

private void writeData(Socket clientSocket, MappedByteBuffer byteBuffer){
    Path path = Paths.get(myfile);
    MappedByteBuffer memoryMappedBuffer = null;
        try (FileChannel fChannel = FileChannel.open(path, StandardOpenOption.READ)) {
            memoryMappedBuffer = fChannel.map(FileChannel.MapMode.READ_ONLY, location, size);
        }catch(){
        
    //How can i write memoryMappedBuffer to socket outputStream without copying data...? like
    clientSocket.getOutputStream().write(memoryMappedBuffer .array());
}

如果您自己创建套接字,则可以使用,并使用。它在内部管理套接字

InetSocketAddress address = ...
SocketChannel channel = SocketChannel.open(address);
channel.write(memoryMappedBuffer);
// ...
channel.close(); // Closes the connection
如果您有一个预先存在的套接字,则可以从套接字的输出流创建一个
通道。但是,这会分配一个(重用的)临时缓冲区

WritableByteChannel channel = Channels.newChannel(clientSocket.getOutputStream());
channel.write(memoryMappedBuffer);
// ...
channel.close();

根据您的描述,您希望将文件的内容或文件的一个片段写入套接字,该片段将映射到java进程的虚拟地址空间

内存映射文件通常用于在多个进程之间共享内存,或在进程向同一文件写入数据或从同一文件读取数据时最小化磁盘上的I/O操作(具体示例是Kafka,它使用此过程)

在您的情况下,当您将数据写入套接字时,该套接字有一个缓冲区(不管它是阻塞的还是非阻塞的)。当缓冲区已满时,在接收器确认数据并清除缓冲区之前,您将无法写入。现在,如果接收器速度慢,您将保留加载到主内存中的文件部分很长一段时间,这可能会影响服务器的性能(我想您的服务器不会有一个使用者/客户机)

一个好而有效的解决方案是使用管道流,它以生产者/消费者的方式将数据从服务器发送到消费者(在本例中为套接字)。默认情况下,PipeInputStream使用1024字节的缓冲区(您可以增加它),这意味着对于特定的执行线程,在某一时刻内存中只保留1024字节。如果您的进程有500个客户端,那么您将只消耗500*1024字节=512Kb。如果一个读卡器很慢,那么这个生产者也会很慢,而不会对进程内存造成压力

如果您所要做的只是将各种文件的内容写入套接字,我不知道使用内存映射文件如何帮助您