nanopb can't communicate with google protobuf

1.4k views Asked by At

I have created a simple server client program. I wanted to enable the communication between NanoPb and Protobuf. However, it does not work. Does anyone know what I'm doing wrong?

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 in Google 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);

        }
    }
}

I get the following error message:

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)
1

There are 1 answers

2
jpa On

Here, on the C side, you encode a ListParamResponse message:

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

But on the Java side, you try to decode it as a TestParameter message:

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

Because the message type is wrong, the Java side doesn't find the fields it expects to find.