Protocol buffers 基于nanopb的TCP客户端无法与Java TCP Netty服务器交互

Protocol buffers 基于nanopb的TCP客户端无法与Java TCP Netty服务器交互,protocol-buffers,netty,tcpsocket,protobuf-java,nanopb,Protocol Buffers,Netty,Tcpsocket,Protobuf Java,Nanopb,探索nanopb客户机服务器示例并尝试使用其他protobuf库。我的问题是: nanopb生成的protobuf是否与使用谷歌protobufjava的其他语言(如java)生成的protobuf兼容?nanopb中编码的protobuf可以被java中的google protobuf库解码,反之亦然?我在C protobuf客户端和Java protobuf服务器之间的套接字通信中遇到了一个问题。 C客户端代码遵循nanopb网络_服务器示例,客户端服务器共享相同的原型消息。C客户机和C服务

探索nanopb客户机服务器示例并尝试使用其他protobuf库。我的问题是: nanopb生成的protobuf是否与使用谷歌protobufjava的其他语言(如java)生成的protobuf兼容?nanopb中编码的protobuf可以被java中的google protobuf库解码,反之亦然?我在C protobuf客户端和Java protobuf服务器之间的套接字通信中遇到了一个问题。 C客户端代码遵循nanopb网络_服务器示例,客户端服务器共享相同的原型消息。C客户机和C服务器工作正常,同样,Java客户机和Java服务器也工作正常。然而,当C客户端连接到Netty TCP服务器时,它并没有显示任何输出

message Sample {
        optional string value = 1;
}
选项已定义最大大小

C客户端代码段:

  
  Sample message = Sample_init_default;        
  pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));        
  strcpy(message.value,"device1");
  status = pb_encode(&stream, Sample_fields, &message);        
  message_length = stream.bytes_written;                
  if (!status)
  {
            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));            
            return 1;
  }  
  pb_ostream_t output = pb_ostream_from_socket(sockfd);    
  if (!pb_encode_delimited(&output, Sample_fields, &message))
  {            
   printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
  }
// main calls run method

public void run() {
        EventLoopGroup ServerGroup = new NioEventLoopGroup();
        try{     
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(ServerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100)
                .childHandler(new ServerInitializer());
            ChannelFuture future = bootstrap.bind(1234).sync();
            future.channel().closeFuture().sync();
        } catch(Exception ex) {
            System.out.println(ex);
        }
        finally{
            System.out.println("Logging Off");
            ServerGroup.shutdownGracefully();
        }
    }

public class ServerInitializer extends ChannelInitializer<SocketChannel> {
     @Override
     public void initChannel(SocketChannel ch) throws Exception {
        try {       
           ChannelPipeline p = ch.pipeline();
           
           //add decoders and encoders
           p.addLast(new ProtobufVarint32FrameDecoder());
           p.addLast(new ProtobufDecoder(SampleProtos.Sample.getDefaultInstance()));
           p.addLast(new ProtobufVarint32LengthFieldPrepender());
           p.addLast(new ProtobufEncoder());
           
           //handler for business logic
           p.addLast(new ServerHandler());
        } catch (Exception ex) {
           System.out.println(ex);
        }
     }
}


public class ServerHandler extends ChannelInboundHandlerAdapter {
.........
@Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
      System.out.println("Channel Read...");
      
      try {
          SampleProtos.Sample sample = (SampleProtos.Sample)msg;
          System.out.println("Value Read: " + sample.getValue());
          sample = sample.toBuilder().setValue("Server Response").build();
          ctx.writeAndFlush(sample);
     } catch (Exception ex){
         System.out.println(ex);
     }
  }
  
}  
  
Java TCP服务器(基于Netty)代码段:

  
  Sample message = Sample_init_default;        
  pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));        
  strcpy(message.value,"device1");
  status = pb_encode(&stream, Sample_fields, &message);        
  message_length = stream.bytes_written;                
  if (!status)
  {
            printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));            
            return 1;
  }  
  pb_ostream_t output = pb_ostream_from_socket(sockfd);    
  if (!pb_encode_delimited(&output, Sample_fields, &message))
  {            
   printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
  }
// main calls run method

public void run() {
        EventLoopGroup ServerGroup = new NioEventLoopGroup();
        try{     
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(ServerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100)
                .childHandler(new ServerInitializer());
            ChannelFuture future = bootstrap.bind(1234).sync();
            future.channel().closeFuture().sync();
        } catch(Exception ex) {
            System.out.println(ex);
        }
        finally{
            System.out.println("Logging Off");
            ServerGroup.shutdownGracefully();
        }
    }

public class ServerInitializer extends ChannelInitializer<SocketChannel> {
     @Override
     public void initChannel(SocketChannel ch) throws Exception {
        try {       
           ChannelPipeline p = ch.pipeline();
           
           //add decoders and encoders
           p.addLast(new ProtobufVarint32FrameDecoder());
           p.addLast(new ProtobufDecoder(SampleProtos.Sample.getDefaultInstance()));
           p.addLast(new ProtobufVarint32LengthFieldPrepender());
           p.addLast(new ProtobufEncoder());
           
           //handler for business logic
           p.addLast(new ServerHandler());
        } catch (Exception ex) {
           System.out.println(ex);
        }
     }
}


public class ServerHandler extends ChannelInboundHandlerAdapter {
.........
@Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
      System.out.println("Channel Read...");
      
      try {
          SampleProtos.Sample sample = (SampleProtos.Sample)msg;
          System.out.println("Value Read: " + sample.getValue());
          sample = sample.toBuilder().setValue("Server Response").build();
          ctx.writeAndFlush(sample);
     } catch (Exception ex){
         System.out.println(ex);
     }
  }
  
}  
  
//主调用run方法
公开募捐{
EventLoopGroup ServerGroup=新的NioEventLoopGroup();
试试{
ServerBootstrap bootstrap=newserverbootstrap();
bootstrap.group(服务器组)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,100)
.childHandler(新的服务器初始值设定项());
ChannelFuture=bootstrap.bind(1234.sync();
future.channel().closeFuture().sync();
}捕获(例外情况除外){
系统输出打印项次(ex);
}
最后{
System.out.println(“注销”);
ServerGroup.shutdownGracefully();
}
}
公共类ServerInitializer扩展了ChannelInitializer{
@凌驾
public void initChannel(SocketChannel ch)引发异常{
试试{
ChannelPipeline p=通道管道();
//添加解码器和编码器
p、 addLast(新的ProtobufVarint32FrameDecoder());
p、 addLast(新的ProtobufDecoder(SampleProtos.Sample.getDefaultInstance());
p、 addLast(新的Protobufvarint32长字段Prepender());
p、 addLast(新ProtobufEncoder());
//业务逻辑处理程序
p、 addLast(新的ServerHandler());
}捕获(例外情况除外){
系统输出打印项次(ex);
}
}
}
公共类ServerHandler扩展ChannelInboundHandlerAdapter{
.........
@凌驾
public void channelRead(ChannelHandlerContext ctx,Object msg)引发异常{
System.out.println(“通道读取…”);
试一试{
SampleProtos.Sample Sample=(SampleProtos.Sample)msg;
System.out.println(“读取值:+sample.getValue());
sample=sample.toBuilder().setValue(“服务器响应”).build();
ctx.writeAndFlush(样本);
}捕获(例外情况除外){
系统输出打印项次(ex);
}
}
}  

对于C客户机,服务器输出为空,但显示Java Netty客户机的客户机发送数据。我的代码失败的原因有什么建议吗?提前感谢。

解决了这个问题。发现在客户端设置了最大大小的选项,但java服务器端没有选项。当我删除客户端的选项并使用encode_字符串而不是strcpy时,它起了作用!这是否意味着字符数组和字符串在nanopb中的编码不同?在这种情况下,了解传输的实际二进制数据很重要。您可以使用wireshark或其他TCP分析工具查看。谢谢,我们将尝试wireshark和pcap。。观察到Java服务器到C客户端的响应是正确的,即使在Java端没有使用选项,而是在C端使用。。在客户端使用与网络服务器相同的代码