2012-06-05 16 views
0

我想写一个netty通道的原始字节。我认为我可以这样做,首先创建一个ChannelBuffer,用字节填充(例如来自Kryo序列化程序),然后将该ChannelBuffer写入netty Channel。写一个ChannelBuffer到一个Netty通道抛出java.io.NotSerializableException

下面是相关的代码,在那里我只是填一些字节到一个在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); 

感谢您的指点!

回答

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的输出,并且您的对象应该是输入。

最好的办法是写一个新的ChannelHandler,它使用Kryo来编码你的对象。当Kryo在Netty管道中作为处理程序工作时,您可能会发现一些提高的效率。

+0

现在,我浏览netty的源代码和文档,这一切都很有意义。谢谢 ! – gsimard

相关问题