协议缓冲区挑战

4

我正在开发一个使用协议缓冲作为序列化器的应用程序。我的应用程序将是服务器的客户端。要求在发送protobuf数据之前,必须在protobuf数据前面添加4个字节的大小。我正在使用Netty作为套接字库。我已经使用了Netty的内置协议缓冲编码器和解码器,但仍然无法获得正确的结果。这是我运行的代码:

管道代码

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;
    }

}

任何帮助都会有所帮助,谢谢。

2个回答

0

我已经解决了这个问题。我的做法是根据要交换的protobuf数据编写自己的编码器和解码器。主要问题在于通道上的字节序。


0

你需要更详细地解释一下哪些方面出了问题。如果我查看protobuf RPC Java库(https://code.google.com/p/protobuf-rpc-pro/)中的代码,类名为DuplexTcpClientPipelineFactory或DuplexTcpServerPipelineFactory,这基本上是与你的代码相同的代码,并且“有效”。也许protobuf-rpc-pro库已经可以满足你的需求。

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;
}

你的服务器是Netty服务器还是仅仅是Netty客户端?


我正在连接到一个C#服务器。我需要一个4字节长度的protobuf解码器。 - Arsene
我不是C#专家,但我猜你需要找出C# int "length"的二进制格式 - 4字节,有符号或无符号,小端或大端。然后根据这个格式调整客户端Java代码来进行帧处理。如果你使用io.netty.handler.codec.LengthFieldPrepender作为FRAME_ENCODER和LengthFieldBasedFrameDecoder作为FRAME_DECODER(也许只有服务器需要),它可能会起作用。 - pjklauser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接