Java 如何修复从netty服务器下载的不完整内容

Java 如何修复从netty服务器下载的不完整内容,java,netty,Java,Netty,我正在实现一些简单的netty服务器和客户端来发送和修改文件。类似于云存储的东西 我有一个服务器,它处理传入的请求并将文件发送回客户端。我还希望我的应用程序能够处理大文件,这就是为什么我将这些文件分成块并逐块发送。但有一个问题我无法解决 比如说: 我们在服务器上有一个4 gb文件 它被分成4万块 然后它们被发送到客户端应用程序,我可以看到服务器上的所有区块都被写入套接字,因为我使用int字段作为消息编号(区块编号),并将正在写入的消息编号放入日志 但是,当客户机接收到消息(块)时,对于大文件

我正在实现一些简单的netty服务器和客户端来发送和修改文件。类似于云存储的东西

我有一个服务器,它处理传入的请求并将文件发送回客户端。我还希望我的应用程序能够处理大文件,这就是为什么我将这些文件分成块并逐块发送。但有一个问题我无法解决

比如说:

  • 我们在服务器上有一个
    4 gb
    文件
  • 它被分成4万块
  • 然后它们被发送到客户端应用程序,我可以看到服务器上的所有区块都被写入套接字,因为我使用int字段作为消息编号(区块编号),并将正在写入的消息编号放入日志
但是,当客户机接收到消息(块)时,对于大文件,该过程不会成功完成,客户机只接收到部分(取决于文件大小)块

client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29055
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29056
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29057
客户端开始接收连续消息-
1、2、3、4。。。27878、27879
,然后毫无例外地停止,尽管来自服务器的最后一条消息是,例如40000

差点忘了说我在客户端应用程序中使用了JavaFX

因此,我尝试使用xms xmx java vm选项,但没有任何帮助

服务器

public class Server {
    public void run() throws Exception {
        EventLoopGroup mainGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(mainGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(
                                    new ObjectDecoder(Constants.FRAME_SIZE, ClassResolvers.cacheDisabled(null)),
                                    new ObjectEncoder(),
                                    new MainHandler()
                            );
                        }
                    })
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture future = b.bind(8189).sync();
            future.channel().closeFuture().sync();
        } finally {
            mainGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new Server().run();

    }
}
分块发送文件的方法

private void sendFileToClient(ChannelHandlerContext ctx, String fileName) throws IOException {
        Path path = Paths.get("server_storage/" + fileName);
        if (Files.exists(path)) {
            if (Files.size(path) > Constants.FRAME_SIZE) {
                sendServerDataFrames(ctx, path);
                ctx.writeAndFlush(new FileRequest(FileCommand.LIST_FILES));
            } else {
                FileMessage fm = new FileMessage(path);
                ctx.writeAndFlush(fm);
            }
        }
    }

    private void sendServerDataFrames(ChannelHandlerContext ctx, Path path) throws IOException {
        byte[] byteBuf = new byte[Constants.FRAME_CHUNK_SIZE];

        FileMessage fileMessage = new FileMessage(path, byteBuf, 1);
        FileRequest fileRequest = new FileRequest(FileCommand.SEND_PARTIAL_DATA, fileMessage);

        FileInputStream fis = new FileInputStream(path.toFile());
        int read;
        while ((read = fis.read(byteBuf)) > 0) {
            if (read < Constants.FRAME_CHUNK_SIZE) {
                byteBuf = Arrays.copyOf(byteBuf, read);
                fileMessage.setData(byteBuf);
            }
            ctx.writeAndFlush(fileRequest);
            fileMessage.setMessageNumber(fileMessage.getMessageNumber() + 1);
        }

        System.out.println("server_storage/" + path.getFileName() +  ", server last frame number: " + fileMessage.getMessageNumber());
        System.out.println("server_storage/" + path.getFileName() +  ": closing file stream.");

        fis.close();
    }
这就是我在服务器上看到的

server_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 42151
server_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 42152
server_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso, server last frame number: 42153
server_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: closing file stream.
这是一个客户机

client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29055
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29056
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29057
从客户端向服务器发送文件时没有问题。我可以在调试器和windows任务管理器中看到这两个进程同时工作,但当文件从服务器发送到客户端时,情况并非如此。首先读取所有数据块,然后将其发送给客户端,客户端开始接收这些数据块,但无法获取所有数据块。

请帮忙。我不知道会是什么。提前感谢。

请确保在未来的
writeAndFlush
中捕获异常,它们可能包含您问题的线索,请参阅如何阅读这些异常的示例谢谢。找到原因真的很有帮助。很明显,netty无法释放messge从服务器获取的内存,因为message类未实现ReferenceCounted接口。解决此问题的另一种方法是将a与a结合使用,因此只有在网络层处理了Yes的第一部分可能重复时,才发送文件的下一部分,与其再发明一个字节码,不如使用已经实现的功能。请确保在未来的
writeAndFlush
中捕获异常,它们可能包含问题的线索,请参阅如何读取这些异常的示例谢谢。找到原因真的很有帮助。很明显,netty无法释放messge从服务器获取的内存,因为message类未实现ReferenceCounted接口。解决此问题的另一种方法是将a与a结合使用,因此只有在网络层处理了Yes的第一部分可能重复时,才发送文件的下一部分,最好使用已经实现的功能,而不是再发明一个字节。
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29055
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29056
client_storage/DVD5_OFFICE_2010_SE_SP2_VOLUME_X86_RU-KROKOZ.iso: 29057