我想将原始字节写入netty频道。我想我可以通过首先创建一个ChannelBuffer,用字节填充它(比如来自Kryo序列化程序),然后将ChannelBuffer写入netty频道来实现这一点。
这是相关代码,我只是将一些字节填入ctor中的ChannelBuffer并尝试在连接时发送它:
/**
* Handler implementation for the object echo client. It initiates the
* ping-pong traffic between the object echo client and server by sending the
* first message to the server.
*/
public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
private final ChannelBuffer firstMessage;
/**
* Creates a client-side handler.
*/
public ObjectEchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException(
"firstMessageSize: " + firstMessageSize);
}
firstMessage = ChannelBuffers.buffer(8192);
for (int i = 0; i < firstMessageSize; i++) {
firstMessage.writeByte(i % 256);
}
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message if this handler is a client-side handler.
// e.getChannel().write(firstMessage);
Channels.write(ctx, e.getFuture(), firstMessage);
}
}
这似乎不起作用,因为它抛出了这个异常:
java.io.NotSerializableException: org.jboss.netty.buffer.BigEndianHeapChannelBuffer
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.jboss.netty.handler.codec.serialization.ObjectEncoder.encode(ObjectEncoder.java:80)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:61)
at org.jboss.netty.channel.Channels.write(Channels.java:626)
at org.jboss.netty.channel.Channels.write(Channels.java:587)
at ca.gsimard.spacecraft.client.ObjectEchoClientHandler.channelConnected(ObjectEchoClientHandler.java:83)
at ca.gsimard.spacecraft.client.ObjectEchoClientHandler.handleUpstream(ObjectEchoClientHandler.java:75)
at org.jboss.netty.channel.Channels.fireChannelConnected(Channels.java:227)
at org.jboss.netty.channel.socket.nio.NioWorker$RegisterTask.run(NioWorker.java:784)
at org.jboss.netty.channel.socket.nio.NioWorker.processRegisterTaskQueue(NioWorker.java:250)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:192)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
我确信这是微不足道的,可能是错误的做法,因为我似乎无法找到任何与此有相同错误的人。我现在正在使用Netty 3.3.0。
我可以通过创建一个正确大小的byte []并将ChannelBuffer的内容复制到它来实现这一点,但我希望有一个更直接的解决方案来避免无用的字节复制。
byte[] array = new byte[firstMessage.writerIndex()];
firstMessage.readBytes(array);
e.getChannel().write(array);
感谢您的任何指示!
答案 0 :(得分:3)
查看堆栈跟踪,我观察了这两行:
at org.jboss.netty.handler.codec.serialization.ObjectEncoder.encode(ObjectEncoder.java:80)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:61
这对我来说意味着您的管道包含ObjectEncoder,它正在尝试序列化ChannelBuffer。由于您的对象已由Kryo编码,因此您不需要ObjectEncoder。
或换句话说(没有Kryo),ChannelBuffer应该是ObjectEncoder的输出,你的对象应该是输入。
最好的办法是编写一个使用Kryo编码对象的新ChannelHandler。当Kryo将其作为Netty管道中的处理程序时,您可能会发现一些额外的效率。