2017-09-15 46 views
0

我已经创建了一个简单的服务器客户端程序。 我想启用NanoPb和Protobuf之间的通信。 但是,它不起作用。有谁知道我做错了什么?nanopb无法与谷歌protobuf

TestParameterProto.proto:

syntax = "proto2"; 
import "nanopb.proto"; 

message ListParamRequest { 
} 


message TestParameter { 

    required int32 height = 1 [default = 0] ; 
    required int32 width = 2; 

} 

message ListParamResponse { 
    repeated TestParameter param = 1; 
} 

TestParameterProto.options:

TestParameter.height  max_count:1000 
TestParameter.width   max_count:1000 

server.c:

#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <dirent.h> 
#include <stdio.h> 
#include <string.h> 

#include <pb_encode.h> 
#include <pb_decode.h> 

#include "TestParameterProto.pb.h" 
#include "common.h" 

/* This callback function will be called once during the encoding. 
* It will write out any number of FileInfo entries, without consuming unnecessary memory. 
* This is accomplished by fetching the filenames one at a time and encoding them 
* immediately. 
*/ 
bool listdir_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) 
{ 
    TestParameter param = {}; 


     param.height = 10; 
     param.width = 2; 

     /* This encodes the header for the field, based on the constant info 
     * from pb_field_t. */ 
     if (!pb_encode_tag_for_field(stream, field)) 
      return false; 

     /* This encodes the data for the field, based on our FileInfo structure. */ 
     if (!pb_encode_submessage(stream, TestParameter_fields, &param)) 
      return false; 


    return true; 
} 

/* Handle one arriving client connection. 
* Clients are expected to send a ListFilesRequest, terminated by a '0'. 
* Server will respond with a ListFilesResponse message. 
*/ 
void handle_connection(int connfd) 
{ 


    /* List the files in the directory and transmit the response to client */ 
    { 
     ListParamResponse response = {}; 
     pb_ostream_t output = pb_ostream_from_socket(connfd); 


      /* Directory was found, transmit filenames */ 

      response.param.funcs.encode = &listdir_callback; 


     if (!pb_encode(&output, ListParamResponse_fields, &response)) 
     { 
      printf("Encoding failed: %s\n", PB_GET_ERROR(&output)); 
     } 
    } 


} 

int main(int argc, char **argv) 
{ 
    int listenfd, connfd; 
    struct sockaddr_in servaddr; 
    int reuse = 1; 

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 

    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(8000); 
    if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0) 
    { 
     perror("bind"); 
     return 1; 
    } 

    if (listen(listenfd, 5) != 0) 
    { 
     perror("listen"); 
     return 1; 
    } 

    for(;;) 
    { 
     /* Wait for a client */ 
     connfd = accept(listenfd, NULL, NULL); 

     if (connfd < 0) 
     { 
      perror("accept"); 
      return 1; 
     } 

     printf("Got connection.\n"); 

     handle_connection(connfd); 

     printf("Closing connection.\n"); 

     close(connfd); 
    } 

    return 0; 
} 

client.java在谷歌的Protobuf:

package com.example.tutorial.main; 

import java.net.Socket; 


import com.example.tutorial.googleprotobuf.TestParameterProto.TestParameter; 


public class PersonReader1 {  
    public static void main(String[] args) throws Exception { 

     try (Socket clientSocket = new Socket("192.168.178.26", 8000)) { 


      TestParameter p = TestParameter.parseFrom(clientSocket.getInputStream()); 

      int i = p.getHeight(); 
      int j = p.getWidth(); 
      System.out.println("Height " + i); 
      System.out.println("Width " + j); 

     } 
    } 
} 

我收到以下错误信息:

Exception in thread "main" com.google.protobuf.InvalidProtocolBufferException: Message missing required fields: height, width 
    at com.google.protobuf.UninitializedMessageException.asInvalidProtocolBufferException(UninitializedMessageException.java:81) 
    at com.google.protobuf.AbstractParser.checkMessageInitialized(AbstractParser.java:72) 
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:238) 
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:244) 
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49) 
    at com.google.protobuf.GeneratedMessageV3.parseWithIOException(GeneratedMessageV3.java:311) 
    at com.example.tutorial.googleprotobuf.TestParameterProto$TestParameter.parseFrom(TestParameterProto.java:638) 
    at com.example.tutorial.main.PersonReader1.main(PersonReader1.java:15) 

回答

0

这里,在C面,则编码ListParamResponse消息:

if (!pb_encode(&output, ListParamResponse_fields, &response)) 

但在Java端,你尝试将其作为一个解码TestParameter消息:

TestParameter p = TestParameter.parseFrom(clientSocket.getInputStream()); 

因为消息类型是错误的,在Java端没有找到,预计t时的领域o找到。

+0

感谢您的快速回复。 是的你是对的。 :D 嗯,我还有一个愚蠢的问题。我怎样才能从ListParamResponse解析? ListParamRequest p = ListParamRequest.parseFrom(clientSocket.getInputStream()); //然后呢? – Cooper47

+0

@ Cooper47我不太确定Java API是如何工作的,但这个链接可能有所帮助:https://developers.google.com/protocol-buffers/docs/javatutorial – jpa

+0

它的工作原理!非常感谢你 ! – Cooper47