4

I am developing an application that uses the protocol buffer as a serializer . My application will be a client to a server. The requirement is that before sending the protobuf data I have to prepend the size of the protobuf data with 4 bytes. I am using Netty as my socket library. I have used the in-built protocolbuffer encoder and decoder of netty but I am still not getting the right result. This is the code I am running: Pipeline code

public class SmpPipelineFactory implements ChannelPipelineFactory {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 
     */
    public SmpPipelineFactory() {
    }

    @Override
    public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline p = pipeline();

        // Add Decoders
        p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());      
        //p.addLast("frameDecoder",  new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));        
        p.addLast("protobufDecoder", new ProtobufDecoder(Pdu.getDefaultInstance()));

        // Add encoders
        p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());
        //p.addLast("frameEncoder", new LengthFieldPrepender(4));
        p.addLast("protobufEncoder", new ProtobufEncoder());

        p.addLast("handler", new SmpChannelConnector());

        return p;
    }

}

Any help will help Thank you.

Arsene
  • 1,037
  • 4
  • 20
  • 47

2 Answers2

0

you need to explain a bit more about what is not working for you. If i look at the code in the protobuf RPC java library (https://code.google.com/p/protobuf-rpc-pro/ ) the class is DuplexTcpClientPipelineFactory or DuplexTcpServerPipelineFactory, which is basically the same code as your's and it "works". Maybe the protobuf-rpc-pro library can already do what you need.

public ChannelPipeline getPipeline() throws Exception {
    ChannelPipeline p = pipeline();

    RpcSSLContext ssl = bootstrap.getSslContext();
    if ( ssl != null ) {
            p.addLast(Handler.SSL, new SslHandler(ssl.createClientEngine()) );
    }

    p.addLast(Handler.FRAME_DECODER, new ProtobufVarint32FrameDecoder());
    p.addLast(Handler.PROTOBUF_DECODER, new ProtobufDecoder(DuplexProtocol.WirePayload.getDefaultInstance(),bootstrap.getExtensionRegistry()));

    p.addLast(Handler.FRAME_ENCODER, new ProtobufVarint32LengthFieldPrepender());
    p.addLast(Handler.PROTOBUF_ENCODER, new ProtobufEncoder());

    // the connectResponseHandler is swapped after the client connection
    // handshake with the RpcClient for the Channel
    p.addLast(Handler.CLIENT_CONNECT, new ClientConnectResponseHandler());

    return p;
}

is your server a netty server , or just a netty client?

pjklauser
  • 1,156
  • 11
  • 13
  • I am connecting to a C# server. I need a 4 byte length protobuf decoder. – Arsene Mar 12 '13 at 11:08
  • i'm not the C# expert - but i guess you need to find out what is the binary format of the C# int "length" - 4bytes, signed or unsigned, litte-endian or big-endian. Then adapt the client java code to frame using this format. It might just work if you use the io.netty.handler.codec.LengthFieldPrepender as FRAME_ENCODER and LengthFieldBasedFrameDecoder for the FRAME_DECODER ( which maybe only the server needs ). – pjklauser Mar 13 '13 at 20:23
0

I have solved the issue. What I did is to write my own encoder and decoder based upon the protobuf data to be exchange. The main issue here was the endianess of the bytes over the channel.

Arsene
  • 1,037
  • 4
  • 20
  • 47