繁体   English   中英

如何在没有副本的情况下将 MappedByteBuffer 写入套接字输出流(服务器到客户端)

[英]How to write MappedByteBuffer to socket outputstream (server to client) with no copy

在 Java 代码中,我有一个使用 MappedByteBuffer 映射的文件区域,我需要将其发送到客户端(写入 Outputstream)。 我需要确保在发送/写入套接字时,由于 memory 限制,它不会创建任何副本。 我怎样才能做到这一点? 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());
}

如果您自己创建套接字,则可以改用SocketChannel.open()并使用write(ByteBuffer) 它在内部管理套接字。

InetSocketAddress address = ...
SocketChannel channel = SocketChannel.open(address);
channel.write(memoryMappedBuffer);
// ...
channel.close(); // Closes the connection

如果您有一个预先存在的套接字,您可以从套接字的 output stream 创建一个Channel 但是,这会分配一个(重用的)临时缓冲区。

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

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

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

在您的情况下,当您将数据写入套接字时,该套接字有一个缓冲区(无论它是阻塞的还是非阻塞的)。 当缓冲区已满时,您将无法写入,直到接收方确认数据并清除缓冲区。 现在,如果接收器很慢,您将长时间保留加载到主 memory 的文件的那部分,这可能会影响服务器的性能(我想您的服务器不会有一个消费者/客户端) .

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

如果您要做的就是将各种文件的内容写入sockets,我不知道使用内存映射文件对您有什么帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM