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, ¶m))
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)
Here, on the C side, you encode a
ListParamResponse
message:But on the Java side, you try to decode it as a
TestParameter
message:Because the message type is wrong, the Java side doesn't find the fields it expects to find.