Sending protobuf from a C++ program to a Java program over socket

722 views
Skip to first unread message

Ashwin Venkataraman

unread,
Jun 11, 2015, 9:08:33 PM6/11/15
to prot...@googlegroups.com
Hi,

I am sending a protobuf from a C++ program to a java program using simple sockets. I'm using winsock to serialize my protobuf to a char* before I send it over the network. I am unable to deserialize the data on the Java program and display the actual data for the protobufs. I keep encountering the errors:

1. CodedInputStream encountered a malformed varint.
2. While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either than the input has been truncated or that an embedded message misreported its own length.

What am I doing wrong? I heard there is a problem of byte order between Java and C++. Is that a problem ? Both my program codes are below. Pleas Help !

P.S. - The protobuf is taken from Google's example - Addressbook.

C++ Code:
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include<conio.h>
#include "addressbook.pb.h"

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

using namespace std;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
    cout << "Enter person ID number: ";
    int id;
    cin >> id;
    person->set_id(id);
    cin.ignore(256, '\n');

    cout << "Enter name: ";
    getline(cin, *person->mutable_name());

    cout << "Enter email address (blank for none): ";
    string email;
    getline(cin, email);
    if (!email.empty()) {
        person->set_email(email);
    }

    while (true) {
        cout << "Enter a phone number (or leave blank to finish): ";
        string number;
        getline(cin, number);
        if (number.empty()) {
            break;
        }

        tutorial::Person::PhoneNumber* phone_number = person->add_phone();
        phone_number->set_number(number);

        cout << "Is this a mobile, home, or work phone? ";
        string type;
        getline(cin, type);
        if (type == "mobile") {
            phone_number->set_type(tutorial::Person::MOBILE);
        }
        else if (type == "home") {
            phone_number->set_type(tutorial::Person::HOME);
        }
        else if (type == "work") {
            phone_number->set_type(tutorial::Person::WORK);
        }
        else {
            cout << "Unknown phone type.  Using default." << endl;
        }
    }
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
int main(int argc, char* argv[]) {
    // Verify that the version of the library that we linked against is
    // compatible with the version of the headers we compiled against.
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    tutorial::AddressBook address_book;


    // Add an address.
    PromptForAddress(address_book.add_person());

    {
        int size = address_book.ByteSize();
        char * buffer = new char[size];
        address_book.SerializeToArray(buffer, size);

        WSADATA wsaData;
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo *result = NULL,
            *ptr = NULL,
            hints;
        int iResult;

        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        // Resolve the server address and port
        iResult = getaddrinfo("localhost", "5000", &hints, &result);
        if (iResult != 0) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }

        // Attempt to connect to an address until one succeeds
        for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
        {

            // Create a SOCKET for connecting to server
            ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
                ptr->ai_protocol);

            // Connect to server.
            iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
            if (iResult == SOCKET_ERROR) {
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
                continue;
            }
        freeaddrinfo(result);

        // Send an initial buffer
        iResult = send(ConnectSocket, buffer, (int)strlen(buffer), 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
        printf("Bytes Sent: %ld\n", iResult);

        _getch();
    // Optional:  Delete all global objects allocated by libprotobuf.
    google::protobuf::ShutdownProtobufLibrary();

    return 0;
        }
    }
}


Java Program:


package networkmonitor;

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import java.io.DataInputStream;
import java.io.IOException;
import static java.lang.System.in;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

class NetworkMonitor {
  // Iterates though all people in the AddressBook and prints info about them.
  static void Print(AddressBook addressBook) {
    for (Person person: addressBook.getPersonList()) {
      System.out.println("Person ID: " + person.getId());
      System.out.println("  Name: " + person.getName());
      if (person.hasEmail()) {
        System.out.println("  E-mail address: " + person.getEmail());
      }

      for (Person.PhoneNumber phoneNumber : person.getPhoneList()) {
        switch (phoneNumber.getType()) {
          case MOBILE:
            System.out.print("  Mobile phone #: ");
            break;
          case HOME:
            System.out.print("  Home phone #: ");
            break;
          case WORK:
            System.out.print("  Work phone #: ");
            break;
        }
        System.out.println(phoneNumber.getNumber());
      }
    }
  }

  // Main function:  Reads the entire address book from a file and prints all
  //   the information inside.
  public static void main(String[] args) throws Exception {

      ServerSocket server = null;
      try
      {
         server = new ServerSocket(5000);
      }
      catch (IOException e)
      {
         System.out.println("Error on port: 5000 " + ", " + e);
         System.exit(1);
      }

      System.out.println("Server setup and waiting for client connection ...");
      Socket client = null;
      try
      {
         client = server.accept();
      }
      catch (IOException e)
      {
         System.out.println("Did not accept connection: " + e);
         System.exit(1);
      }

      System.out.println("Client connection accepted. Moving to local port ...");

      try
      {
           DataInputStream inputStream = new DataInputStream(client.getInputStream());
         /*int read;
          byte[] buffer = new byte[1024];
          read = inputStream.read(buffer);
         byte[] readBuffer = new byte[read];
         readBuffer = Arrays.copyOfRange(buffer, 0, read);*/
       
        //AddressBook addressBook = AddressBook.parseFrom(readBuffer);
         AddressBook addressBook = AddressBook.parseFrom(inputStream);
        Print(addressBook);

         in.close();
         client.close();
         server.close();
      }
      catch(IOException e)
      { System.out.println("IO Error in streams " + e);
        e.printStackTrace();}
  }

}


Reply all
Reply to author
Forward
0 new messages