0

netty Channel に raw バイトを書き込みたいです。最初に ChannelBuffer を作成し、(たとえば、Kryo シリアライザーからの) バイトで埋めてから、その ChannelBuffer を netty Channel に書き込むことで、これを行うことができると思いました。

関連するコードは次のとおりです。ここでは、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);

ご指摘ありがとうございます。

4

1 に答える 1

3

スタック トレースを見て、次の 2 行を確認しました。

at org.jboss.netty.handler.codec.serialization.ObjectEncoder.encode(ObjectEncoder.java:80)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:61

これが意味することは、パイプラインに ChannelBuffer をシリアル化しようとしている ObjectEncoder が含まれていることです。オブジェクトはすでに Kryo によってエンコードされているため、ObjectEncoder は必要ありません。

または別の言い方をすると (Kryo を使用しない場合)、ChannelBuffer は ObjectEncoder の出力であり、オブジェクトは入力である必要があります。

最善の策は、 Kryoを使用してオブジェクトをエンコードする新しいChannelHandlerを作成することです。Kryo が Netty パイプラインのハンドラーとして機能すると、効率が向上する場合があります。

于 2012-06-05T17:10:43.387 に答える