目 录CONTENT

文章目录

netty中ctx.writeAndFlush()没有将数据发送出去

成培培
2024-09-27 / 0 评论 / 0 点赞 / 41 阅读 / 0 字

问题描述:

因为某些极端网络环境,导致我传文件非常非常不方便,所以想到写了这么一个小工具,进行点对点的文件传输。现已放到github,https://github.com/chengpei/file-transfer

开发过程中遇到一个奇怪的问题,在我接收完了文件内容后,准备发送一个文件接收完成的指令,结果并没有发送出去,也就是下面倒数第26行

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (!showProgressThread.isAlive()) {
            sending = true;
            startTime = System.currentTimeMillis();
            showProgressThread.start();
        }
        ByteBuf byteBuf = (ByteBuf) msg;
        int readableBytes = byteBuf.readableBytes();
        byte[] bytes = new byte[readableBytes];
        byteBuf.readBytes(bytes);
        fos.write(bytes);
        byteBuf.release();
        totalSize += readableBytes;
        count++;
        if (totalSize == prepareSendFileCommand.getFileSize()) {
            if (fos != null) {
                fos.close();
                sending = false;
                log.info("传输结束,耗时: {},平均速度:{}/s", getTimeStr(System.currentTimeMillis() - startTime), getNetFileSizeDescription(totalSize / (System.currentTimeMillis() - startTime) / 1000));
            }
            ctx.pipeline().remove(this);
            CompleteFileReceiveCommand completeFileReceiveCommand = new CompleteFileReceiveCommand();
            completeFileReceiveCommand.setPrepareSendFileCommand(prepareSendFileCommand);
            completeFileReceiveCommand.setElapsedTime(System.currentTimeMillis() - startTime);
            ctx.writeAndFlush(completeFileReceiveCommand);
            ConsoleManager.getInstance().finshRunningTask(prepareSendFileCommand.getTaskId());
        }
    }

原因分析:

这里发送的是一个Command对象,没有发送出去很可能是没有经过对应的编码器,当前这个handler是为了接收文件内容特地追加到pipeline链的最前端了,因为接收的文件不需要解码,直接写入文件即可,写完文件这个handler也会移除掉,方便接收后续指令解码。突然想到这里write是不是消息没有传递到pipeline的尾端,直接从当前的handler发回去了,这样就无法经过定义的CommandToByteEncoder编码器了,太久没用Netty了,一时没注意到这个细节。

解决方案:

使用pipeline的writeAndFlush方法就可以了,它的writeAndFlush可以直接从pipeline尾端发送,就可以经过所有的编码器了,替换为以下代码即可

ctx.pipeline().writeAndFlush(completeFileReceiveCommand);

0

评论区