netty:如何就地编辑字节的后端数组?



在我的用例中,我需要在读取或写入之前对每个字节进行xor 到网络。所以我实现了一个双工处理程序来做到这一点。

但是奇怪的是我无法就地编辑输出字节, 而阅读方可以:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ByteBuf buf = (ByteBuf) msg;
ByteBuf res = buf.alloc().buffer(buf.readableBytes());
buf.forEachByte(value -> {
res.writeByte(value ^ cookie);
return true;
});
buf.release();
super.write(ctx, res, promise);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
buf.forEachByte(new ByteProcessor() {
private int i = 0;
@Override
public boolean process(byte value) throws Exception {
buf.setByte(i++, value ^ cookie);
return true;
}
});
super.channelRead(ctx, msg);
}

请注意,write()的 msg 参数在ByteBuf类型中得到保证 它以前的处理程序。

如果我在write()中就地编辑字节,该应用程序无法作为 预期(我不知道会发生什么,我的应用程序是代理程序,如果我 就地编辑 buf,它不起作用:一些代理连接会 给出错误的内容(,所以我必须回退以复制缓冲区进行编辑, 这是一种缓慢的方式,对吧?

write()中的字节有什么特别之处吗?

编辑:

代理服务器将两个通道成对处理,即入站通道和出站通道,以及它们之间的代理数据。

入站通道的流水线:

ch.pipeline().addLast("ReadTimeoutHandler", new ReadTimeoutHandler(30));
ch.pipeline().addLast("WriteTimeoutHandler", new WriteTimeoutHandler(30));
cookie.ifPresent(c -> ch.pipeline().addLast(new FuzzHandler(c)));
ch.pipeline().addLast(new CopyHandler());

出站通道的流水线:

ch.pipeline().addLast(new CopyHandler());

CopyHandler将相互write()配对的通道。

我发现了这个问题。

在我的代码的某些路径中,我Unpooled.wrappedBuffer()一个静态字节数组并执行write(),因此,如果出站处理程序中的write()直接修改缓冲区,它将更改字节数组并影响下一次重用,因此写入网络的内容在一半时间内是错误的。

所以解决方案是复制字节数组:

ByteBuf buf = ctx.alloc().buffer(src.length);
buf.writeBytes(src);

顺便说一句,就地修改缓冲区的正确方法是什么?setByte()应该使用readerIndex作为偏移量?

ByteBuf buf = (ByteBuf) msg;
final int readerIndex = buf.readerIndex();
buf.forEachByte(new ByteProcessor() {
private int i = 0;
@Override
public boolean process(byte value) throws Exception {
buf.setByte(readerIndex + i, value ^ cookie);
i++;
return true;
}
});

一般来说,应该可以就地调整它。我怀疑您可能会在多次写入相同的缓冲区(或共享同一存储的不同缓冲区(时看到问题。

相关内容

最新更新